# Elastic Path Documentation > API, Commerce Manager, Guides and Documentation 🚀 This file contains all documentation content in a single document following the llmstxt.org standard. ## Account Authentication Settings You can use the Account Authentication Settings endpoint to retrieve or modify how settings controlling account and account member authentication. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Account Management Authentication Commerce provides authentication tokens for an `Account` and an `Account Member`. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Account Management Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; An Account represents the entity that participates in a Commerce transaction. Accounts can have Carts, Orders, Subscriptions, and Addresses. Each account can have multiple account members, which represent users and can transact on behalf of the account. In a typical B2C scenario, an account usually has a single account member. However, this functionality can also be used to support use cases such as family accounts, allowing multiple family members to transact on behalf of their shared account. In a B2B scenario, an account will have multiple members from a business unit, all of whom can transact on behalf of their organization. Accounts can be grouped together using Account Tags, and those tags can be used to apply discounts and promotions. ## Accounts vs Customers Accounts is the next generation of [Customers](/docs/customer-management/customers). Customers are not going anywhere, but accounts offers more capabilities. We recommend using Accounts for any of your new use cases. | Feature | Customers | Accounts | |---------------------------------------------------------------------------------------------|-----------|----------| | B2C Accounts | ✅ | ✅ | | Family Accounts | ⛔️ | ✅ | | B2B Accounts | ⛔️ | ✅ | | Authentication: Shopper impersonation | ⛔️ | ✅ | | Authentication: OpenID support | ✅ | ✅ | | Authentication: One time passwords, and password reset | ⛔️ | ✅ | | Authentication: Configurable token expiry | ⛔️ | ✅ | | Cart association | ✅ | ✅ | | Shopper specific Promotions | Limited | ✅ | | Shopper specific Catalogs | ✅ | ✅ | | Addresses | ✅ | ✅ | | [Personal Data Support (GDPR,CCPA,...)](/docs/api/personal-data/personal-data-introduction) | ✅ | ✅ | Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## Account Members An `Account Member` resource is a user that you can add to accounts using account memberships. Account members API is read only, and you cannot add users using this API. There is a 1 to 1 correspondence between User Authentication Info and an Account Member, the corresponding objects have the same id. You must use the `user_authentication_info` object to create users in the authentication realm of account authentication settings. For more information on adding account members, see the [Adding Accounts and Account Members](/guides/How-To/Accounts/add-account-and-member) section. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Account Membership Settings Account Membership Settings allow Account Members to be associated to, at most, N accounts at a time. You can set this value to any number up to 10,000. The default value is 10,000. This setting is only applied to new account memberships. If an account member is added to 3 accounts, and the setting is reduced to 1, the account member remains in the 3 accounts and can no longer be added to more. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Account Membership The `Account Membership` resource represents the relationship between an account and an account member. This relationship is many to many. Each account can have multiple account members, and each account member can be a member of multiple accounts. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Account Tags Account Tags are custom labels or metadata that can be attached to accounts to help organize and filter them based on specific attributes or criteria. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Accounts An Account represents the entity that participates in a Commerce transaction. Accounts can have Carts, Orders, Subscriptions, and Addresses. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Add Account Tags import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Add Account Tags onto an Account. Please note that after adding a tag to an account, the account member token should be regenerated to reflect the updated account status, allowing other services to react accordingly. See [Account Management Authentication Token](/docs/api/accounts/post-v-2-account-members-tokens). Request --- ## Create an Account Tag import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create an Account Tag Request --- ## Delete an Account Tag import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete an Account Tag Request --- ## Delete an Account Membership import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a membership from an account Request --- ## Delete an Account import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a specific account within a store Request --- ## Get an Account Tag import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get an Account Tag Request --- ## Get an Account's Tags Relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a list of Account Tags on an Account Request --- ## Get a List of Account Memberships of Account Member import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can also use `include=account` to retrieve details about the accounts associated with the account memberships. For more information see [including resources](/guides/Getting-Started/includes). You can use pagination with this resource. For more information, see [pagination](/guides/Getting-Started/pagination). ### Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) account memberships. | Operator | Description | | :--- | :--- | | `eq` | Checks whether the values of two operands are equal. If the values are equal, the condition is true. | | `like` | Checks if the operand contains the specified string. You can use wildcard characters in operand. | | Attribute | Type | Operator | Example | | :--- | :--- | :--- | :--- | | `account_member_id` | `string` | `eq` / `like` | `eq(account_member_id,00000000-0000-1000-8000-0000000)` | Request --- ## Get an Account Member import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get an account member from your store Request --- ## Get all Account Members import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get all account members contained within your store. ### Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) account members. | Attribute | Type | Operator | Example | | :--- | :--- | :--- | :--- | | `email` | `string` | `ilike` | `ilike(email,'ronswanson@example.com')` | | `name` | `string` | `ilike` | `ilike(name,'*swan*')` | | `given_name` | `string` | `ilike`/`is_null` | `ilike(given_name,'ron*')` | | `middle_name` | `string` | `ilike`/`is_null` | `is_null(middle_name)` | | `family_name` | `string` | `ilike`/`is_null` | `is_null(family_name)` | Request --- ## Get an Account Membership import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get an account membership from an account in your store. You can also use `include=account_member` to retrieve details about the account member associated with this account membership. With this option, you can get more information about the account member such as name and email in a single request. For more information see [including resources](/guides/Getting-Started/includes). Request --- ## Get a List of Unassigned Account Members import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this resource to get a list of all account members that are not assigned to an account. ### Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) unassigned account members. | Operator | Description | | :------- | :--------------------------------------------------------------------------------------------------- | | `eq` | Checks whether the values of two operands are equal. If the values are equal, the condition is true. | | `like` | Checks if the operand contains the specified string. You can use wildcard characters in operand. | | Attribute | Type | Operator | Example | | :-------- | :------- | :------------ | :--------------------------------- | | `email` | `string` | `eq` / `like` | `eq(email,ronswanson@example.com)` | | `name` | `string` | `eq` / `like` | `like(name,*swan*)` | :::note You can use pagination with this resource. For more information, see [pagination](/guides/Getting-Started/pagination). ::: Request --- ## Get all Account Memberships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can also use `include=account_member` to retrieve details about the account members associated with the account memberships. With this option, you can get more information about the account members such as name and email in a single request. For more information see [including resources](/guides/Getting-Started/includes). ### Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) account memberships. | Operator | Description | | :--- | :--- | | `eq` | Checks whether the values of two operands are equal. If the values are equal, the condition is true. | | `like` | Checks if the operand contains the specified string. You can use wildcard characters in operand. | | Attribute | Type | Operator | Example | | :--- | :--- | :--- | :--- | | `account_member_id` | `string` | `eq` / `like` | `eq(account_member_id,00000000-0000-1000-8000-0000000)` | Request --- ## Get an Account import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; View a specific account contained within your store Request --- ## Get All Accounts import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to Get all accounts. You can use pagination with this resource. For more information, see [pagination](/guides/Getting-Started/pagination). ### Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) accounts: | Attribute | Operators | Example | |-------------------|-------------------------------|---------------------------------------------------------------| | `id` | `lt`,`le`,`eq`,`gt`,`ge`,`in` | `eq(id,3fa85f64-5717-4562-b3fc-2c963f66afa6)` | | `created_at` | `lt`,`le`,`eq`,`gt`,`ge` | `ge(created_at,2024-04-29T00:00:00.000Z)` | | `updated_at` | `lt`,`le`,`eq`,`gt`,`ge` | `le(updated_at,2024-04-29T00:00:00.000Z)` | | `name` | `eq`,`like` | `like(name,*swan*)` | | `legal_name` | `eq`,`like` | `like(legal_name,*swan*)` | | `registration_id` | `eq`,`like` | `like(registration_id,00000000-0000-1000-8000-*)` | | `external_ref` | `eq`,`like`,`in` | `like(external_ref,16be*)` | | `account_tags` | `contains` | `contains(account_tags,26beb787-be6e-40c3-bbae-9c645820b075)` | Request --- ## Get Account Authentication Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to view account authentication settings --- ## Get Account Membership Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to get all account membership settings. --- ## List Account Tags import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of Account Tags ## Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) Account Tags: | Attribute | Operators | Example | |------------------|-------------------------------|-----------------------------------------------| | `id` | `lt`,`le`,`eq`,`gt`,`ge`,`in` | `eq(id,3fa85f64-5717-4562-b3fc-2c963f66afa6)` | | `created_at` | `lt`,`le`,`eq`,`gt`,`ge` | `ge(created_at,2024-04-29T00:00:00.000Z)` | | `updated_at` | `lt`,`le`,`eq`,`gt`,`ge` | `le(updated_at,2024-04-29T00:00:00.000Z)` | | `name` | `eq`,`like` | `eq(name,AccountName)` | ## Sorting The following attributes are available for sorting. When specified, the results are sorted in ascending order based on the value of the field. To sort in descending order, prefix the attribute with `-`, for example, `-updated_at`. The default sort order is `created_at` in descending order. - `id` - `created_at` - `updated_at` - `name` Request --- ## Generate an Account Management Authentication Token import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Commerce provides authentication tokens for anyone using the Account Management APIs, including accounts and account members. For each element in the list returned by the account member authentication API, a token value is returned. In order for a shopper to authenticate as the account, this value should be set as the `EP-Account-Management-Authentication-Token` header when calling Commerce. This header grants access to additional resources associated with the account, such as [carts](/docs/api/carts/account-cart-associations), [orders](/docs/api/carts/orders), [catalogs with associated rules](/docs/api/pxm/catalog/rules), and [addresses](/docs/api/addresses/addresses-introduction). The set of permissions available to a shopper using an Account Management Authentication token is documented in [Permissions](/docs/authentication/tokens/permissions) Commerce provides authentication tokens for an account and an account member using: - OpenID Connect - Username and password - Self signup - One-time password token - Switch account token Request --- ## Create an Account Membership import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; :::caution You can only create up to 1000 account memberships in an account. ::: Request --- ## Create an Account import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; With the account creation endpoint, you have the ability to create accounts which can optionally have another account as a parent. Request --- ## Update an account member import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; This endpoint can be used to update an account member. Request --- ## Update an Account Membership import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can update and extend an account member details using [core flows](/docs/api/flows/flows#extend-an-existing-resource). However, you cannot update the `account_member_id` of an account member. Request --- ## Update an Account import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update the information contained on an account. Request --- ## Update Account Authentication Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to update account authentication settings Request --- ## Update Account Membership Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to update account membership settings. Request --- ## Remove Account Tags import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Remove Account Tags from an Account. Please note that after removing a tag from an account, the account member token should be regenerated to reflect the updated status, allowing other services to react accordingly. See [Account Management Authentication Token](/docs/api/accounts/post-v-2-account-members-tokens). Request --- ## Update an Account Tag import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update an Account Tag Request --- ## Account Addresses The API to organize account addresses. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Addresses Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; The Addresses API allows you to organize account addresses. Addresses are a sub-resource of `account` resources, an account can have multiple addresses, such as home, work, and neighbour. You can use an account address with either [client_credentials access token](/docs/api/authentication/create-an-access-token) or a combination of [implicit access token](/docs/api/authentication/create-an-access-token) and [Account Management authentication](/docs/api/accounts/post-v-2-account-members-tokens) token. Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## Delete an Account Address import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete an address for an Account. Request --- ## Get an Account Address import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a specific address for an Account. Request --- ## Get Account Addresses import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get all addresses for an Account. You can use pagination with this resource. For more information, see [pagination](/guides/Getting-Started/pagination). ### Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) addresses: | Attribute | Operators | Example | |----------------|---------------------------------|---------------------------------------| | `name` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(name,"*home*")` | | `first_name` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(first_name,"Ron*")` | | `last_name` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(last_name,"*swan*")` | | `phone_number` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(phone_number,"*555*")` | | `company_name` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(company_name,"*enterprises*")` | | `instructions` | `eq`,`in`,`like`,`ilike`,`text` | `text(instructions,"behind bin")` | | `line_1` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(line_1,"*Sunny Street*")` | | `line_2` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(line_2,"*Unit*")` | | `city` | `eq`,`in`,`like`,`ilike`,`text` | `eq(city,"Sunny Town")` | | `county` | `eq`,`in`,`like`,`ilike`,`text` | `eq(county,"Sunnyville")` | | `region` | `eq`,`in`,`like`,`ilike`,`text` | `eq(region,"California")` | | `postcode` | `eq`,`in`,`like`,`ilike`,`text` | `eq(postcode,"SU33 1YY")` | | `country` | `eq`,`in`,`like`,`ilike`,`text` | `eq(country,"GB")` | Request --- ## Create an Account Address import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create an address for an Account. Request --- ## Update an Account Address import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update an address for an Account. Request --- ## Application Keys Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Application keys are used to directly manage access to Organizations and stores. These keys are identified based on their names, and are not associated with a user. You can use application keys to generate `client_credentials` and `implicit tokens`. Unlike [User Credentials](/docs/authentication/security#user-credentials), Application keys are still valid even after a team member is removed from a store or organization. Each organization and store has a specific [rate limit](/guides/Getting-Started/rate-limits). You can fine-tune the performance and availability of your applications that are integrated with our platform by reserving a rate limit for each Application Key. Reserved rate limits ensures that applications using a token generated from that key can make at least that many requests per second. ## Scenarios For example, consider the following two scenarios for using reserved rate limits: - Scenario 1: Suppose you use a key for your store front. You can reduce the risk of customers experiencing throttling while shopping by reserving a majority of your store's rate limit for that store front to ensure a smooth shopping experience. - Scenario 2: If you have a key for the store front but you also need to support several backend processes syncing data across systems, you can reserve a part of your store's rate limit to your store front key. This ensures that the backend process doesn't slow down the store front. Additionally, you can also reserve a rate limit for the key that is associated with most critical backend process. It is important to note that the sum of the reserved value for all keys in your store or organization cannot exceed the total allowed requests per second for that store or organization. For example, suppose a store has a rate limit of 100 requests per second, and there is already a key that has a reserved limit of 80 requests per second. If you try to create a new key with reserved rate limit of 21 requests per second, the request will fail. However, if you reserve only 20 requests per second, it will succeed as it doesn't exceed the store's rate limit. Keys without a reserved rate limits share from the same pool. If the total reserved rate limit across keys reaches the total rate limit for your store or organization, there will be nothing left in the unreserved, shared pool. Keys without a reserved rate limit will experience throttling when they attempt to make requests. Keys with a reserved rate limit can also use this shared pool. Adjustments made to the reserved rate limit may take up to one hour to become effective. The following table describes the management of application keys for organizations and stores. | Organizations | Stores | | --------------- | -------- | | Application keys are granted the same permissions as Org Admins. | Application keys are granted the same permissions as Store Admins. | | Org Admins can view and manage the list of application keys in their organization and all stores belonging to that organization. | Store Admins can view and manage the list of application keys within the store. | | Application keys can be used to manage access to an organization and all stores in the organization. | Application keys can be used to manage access to a store. | ## Best Practices for Application Keys - Assign a descriptive name for the application key associated with its purpose. - Create a unique application key each each distinct type of interactions, such as storefront and back-end interactions. - Do not embed API keys directly in your code. - Do not store API keys in files within your application's source tree. - Regularly review your application keys and delete any that are no longer in use. - Assign a reserved rate limit for your critical application keys. - Do not fully reserve the rate limit for your store or organizations across all keys. Instead, reserve rate limits thoughtfully to ensure that keys without a reserved rate limit can draw from a shared pool when needed. To create your application key, see [Creating an Application Key](/docs/commerce-manager/application-keys/application-keys-cm). Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## Application Keys You can use application keys to generate `client_credentials` and `implicit` tokens. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Create an Application Key import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create an Application Key Request --- ## Delete an Application Key import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete an Application Key Request --- ## Get an Application Key import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get an Application Key Request --- ## List Application Keys import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of Application Keys Request --- ## Update an Application Key import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update an Application Key Request --- ## Authentication import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; All API endpoints require authentication. To authenticate your request, you will need to provide an access token. Access tokens are generated via an [authentication API endpoint](/docs/api/authentication/create-an-access-token). After creating an access token, you can authenticate your request by sending the access token in the `Authorization` header of your request: ```json Authorization: Bearer 212LJ3k0i2382364HIUEjfeJB98yvH ``` :::note Read our [Quick Start guide](/guides/Getting-Started/your-first-api-request) on how to make your first API request. ::: Access tokens expire after 1 hour. You will have to generate a new one. If you’re using our [JavaScript SDK](https://github.com/elasticpath/js-sdk), this is automatically handled for you. ## Client Credentials vs. Implicit Use Case Scenarios There are two authentication methods, `client_credentials` and `implicit`. The `implicit` authentication will generate an access token that has more limited access, restricting access to mostly read-only, whereas the access token from `client_credentials` has full read and write access. Typically, you would use the `implicit` authentication method for client-side browser based applications (i.e. frontend), and `client_credentials` for all administrative tasks (`CRUD`) you need to perform at the backend. ## Shopper Authentication An implicit access token is often used alongside an Account Management authentication token or a Customer token to access resources restricted to a shopper. ### Account Authentication Account Management authentication tokens are available for anyone using the [Account Management APIs](/docs/api/accounts/account-management-introduction). For each element in the list returned by the account member authentication API, a `token` value is returned. In order for a shopper to authenticate as the account, this value should be set as the `EP-Account-Management-Authentication-Token` header when calling Commerce. This header grants access to additional resources associated with the account, such as [carts](/docs/api/carts/account-cart-associations), [orders](/docs/api/carts/get-customer-orders), [catalogs with associated rules](/docs/api/pxm/catalog/rules), and [addresses](/docs/api/addresses/addresses-introduction). The set of permissions available to a shopper using an Account Management Authentication token is documented in [Permissions](/docs/authentication/tokens/permissions#implicit-account-management-authentication-token). For more information on implementing account management authentication tokens, see [Account Management Authentication Tokens](/docs/api/accounts/post-v-2-account-members-tokens). ### Customer Authentication Customer tokens are available for anyone using the [Customer APIs](/docs/customer-management/customers). A customer token provides access to the records of the customer. Use single sign-on or the email address and password of the customer to retrieve the [customer tokens](/docs/customer-management/customer-management-api/customer-tokens). The customer token should be set as the `X-Moltin-Customer-Token` header to access the following APIs: - [Get a Customer](/docs/customer-management/customer-management-api/get-a-customer) - [Update a Customer](/docs/customer-management/customer-management-api/update-a-customer) - [Get Customer Addresses](/docs/api/customer-addresses/get-v-2-customer-addresses) - [Get an Address](/docs/api/customer-addresses/get-v-2-customer-addresses) - [Create an Address](/docs/api/addresses/get-v-2-account-address) - [Update an Address](/docs/api/addresses/put-v-2-account-address) - [Get all Orders](/docs/api/carts/get-customer-orders) - [Get an Order](/docs/api/carts/get-an-order) - [Get Customer Carts](/docs/api/carts/create-a-cart) - [Create an Association between a Customer and a Cart](/docs/api/carts/create-customer-cart-association) - [Delete an Association Between a Customer and a Cart](/docs/api/carts/delete-customer-cart-association) - [Add Promotion to Cart](/docs/api/carts/manage-carts#add-promotion-to-cart) For more information on implementing customer tokens, see [Customer Tokens](/docs/customer-management/customer-management-api/customer-tokens). ## Organization To help with managing stores within an organization, the access token generated for the organization can be used to authenticate requests for any store within the organization. To make a request to a store within the organization: 1. Set the `EP-Org-ID` header with the organization ID 2. Set the `EP-Store-ID` header with the store ID For example, to get all the application keys for a store with ID `9adcc2d3-6a39-4057-bbc1-b036f1d6c735` that is part of the organization with ID `afb3dd03-1c89-4ff8-8611-cf759b15827f`: ```bash curl -X GET 'https://useast.api.elasticpath.com/v2/application-keys' \ -H 'Authorization: Bearer d5525335fedf1b20f081f641d8d32980ec553b5c' \ -H 'EP-Org-ID: afb3dd03-1c89-4ff8-8611-cf759b15827f' \ -H 'EP-Store-ID: 9adcc2d3-6a39-4057-bbc1-b036f1d6c735' ``` ## Authenticating for Use on the Documentation site In order to perform any of the API requests directly on the documentation site, you will need to authenticate to get an access token. After the first request, any subsequent request will continue to use the same access token. Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## Create an Access Token import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; ### Client Credentials A `client_credentials` token is used when the credentials are not publicly exposed, usually a server-side language such as PHP or Node.js. This type of authentication enables `CRUD` access to all resources. `client_id` and `client_secret` are created and managed via [Application Keys](/docs/api/application-keys/create-an-application-key). To see the access granted by a `client_credentials` token, refer to [Permissions](/docs/authentication/tokens/permissions). ### Implicit An `implicit` token is typically used for situations where you are requesting data on the client side and you are exposing your public key. When authenticated implicitly, you can only fetch (`GET`) data with live status (products, categories, brands, etc). The `implicit` token is most appropriate for use inside client-side applications, such as JavaScript. :::caution An `implicit` token can be thought of as a **Read only** token. ::: Request --- ## Account Cart Associations You can create associations between an account and one or more carts. After cart associations exist for an account, those carts are accessible across any device. You can delete associations as required. There are two ways to access the cart: with an [Account Management Authentication Tokens](/docs/api/accounts/post-v-2-account-members-tokens) and without one. ### With an `Account Management Authentication` token These endpoints are for users who authenticated implicitly and require an Account Management Authentication token in the header to access the account cart associations APIs. For more information, see the [Account Token](/docs/api/accounts/post-v-2-account-members-tokens) documentation. #### Cart creation Shoppers create carts and can use any of the carts that they created to check out an order. :::note You can create a cart id, name, and description for the cart. The cart requires a name. Ensure that the string length is greater than or equal to one. Use any symbol in the name and description. For cart id, ensure that you follow the guidelines for safe characters. For more information about cart id naming requirements, see [Safe Characters](/guides/Getting-Started/safe-characters). ::: ### Without an `Account Management Authentication` token These endpoints are for users who use the Client Credentials Token and do not require an account management authentication token in the header to access the account cart associations APIs. For more information, see the [Authentication](/docs/authentication/security) documentation. This user acts as a system administrator and can call any account cart association operations for any account and cart. ### Error Codes You might encounter the following response codes, depending on the scenario: * `400` - `The type does not exist or is not listed as account` - Ensure that the type is `account` and is present. * `403` - `Cannot associate more than one account`. * `403` - `Account does not have the required permissions to fulfill this request`. * `403` - `Invalid json payload` - Check JSON input. The request body must be an array `[]`. If the request body is an object, the error is generated. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Add Custom Discount To Cart Item import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to add a custom discount to cart item. Custom discounts cannot be combined with Elastic Path promotions. If the cart already contains Elastic Path promotions, remove them before adding custom discounts. Request --- ## Add Tax Item to Bundle Component import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to add a tax item to a specific bundle component (component product) within a cart item. :::note There is a soft limit of 5 unique tax items per component product at any one time. ::: Request 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]}},"required":["data"],"title":"CartItemTaxesEntityResponse"},"examples":{"rateTaxItemComponent":{"summary":"Add a rate-based tax item to a bundle component","value":{"data":{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2}}},"amountTaxItemComponent":{"summary":"Add an amount-based tax item to a bundle component","value":{"data":{"type":"tax_item","code":"PST","jurisdiction":"CA-BC","name":"Provincial Sales Tax","amount":250}}}}}},"required":true}} > 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]}},"required":["data"],"title":"CartItemTaxesEntityResponse"},"examples":{"componentRateTaxItem":{"summary":"Rate-based tax item on bundle component","value":{"data":{"id":"4f4e6d37-8c8c-4a1a-b8a3-6cd2efab12de","type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2}}}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"status":{"type":["string","integer"],"description":"The HTTP response code of the error.","examples":["400"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]},"source":{"type":"string","description":"The field or location that caused the validation error. For JSON schema validation errors, this contains the JSON path to the invalid field (e.g., 'data.name', 'request', 'data.items[0].quantity')."},"meta":{"type":"object","description":"Additional metadata associated with the error. May include arbitrary keys.","properties":{"id":{"type":"string","description":"The resource id associated with the error"},"ids":{"type":"array","items":{"type":"string","description":"The resource ids associated with the error"}},"item_ids":{"type":"array","items":{"type":"string","description":"The cart_item ids associated with the error"}},"shipping_group_id":{"type":"string","description":"The shipping group id associated with the error"},"shipping_group_ids":{"type":"array","items":{"type":"string","description":"The shipping group ids associated with the error"}},"cart_id":{"type":"string","description":"The cart id associated with the error"},"code":{"type":"string","description":"The code associated with the error."},"order_id":{"type":"string","description":"The order id associated with the error."},"sku":{"type":"string","description":"The SKU associated with the error."},"email":{"type":"string","format":"email","description":"The email address associated with the error."},"component_product_id":{"type":"string","format":"uuid","description":"The component product ID associated with the error."},"error-meta-key":{"type":"string","description":"Custom error metadata key used for additional error context (e.g., in payment rejections)."},"value":{"description":"The value associated with the error.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"boolean"},{"type":"object","additionalProperties":true},{"type":"array"}]}}}},"title":"Response.ErrorItem"}}},"title":"Response.ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"status":{"type":["string","integer"],"description":"The HTTP response code of the error.","examples":["400"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]},"source":{"type":"string","description":"The field or location that caused the validation error. For JSON schema validation errors, this contains the JSON path to the invalid field (e.g., 'data.name', 'request', 'data.items[0].quantity')."},"meta":{"type":"object","description":"Additional metadata associated with the error. May include arbitrary keys.","properties":{"id":{"type":"string","description":"The resource id associated with the error"},"ids":{"type":"array","items":{"type":"string","description":"The resource ids associated with the error"}},"item_ids":{"type":"array","items":{"type":"string","description":"The cart_item ids associated with the error"}},"shipping_group_id":{"type":"string","description":"The shipping group id associated with the error"},"shipping_group_ids":{"type":"array","items":{"type":"string","description":"The shipping group ids associated with the error"}},"cart_id":{"type":"string","description":"The cart id associated with the error"},"code":{"type":"string","description":"The code associated with the error."},"order_id":{"type":"string","description":"The order id associated with the error."},"sku":{"type":"string","description":"The SKU associated with the error."},"email":{"type":"string","format":"email","description":"The email address associated with the error."},"component_product_id":{"type":"string","format":"uuid","description":"The component product ID associated with the error."},"error-meta-key":{"type":"string","description":"Custom error metadata key used for additional error context (e.g., in payment rejections)."},"value":{"description":"The value associated with the error.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"boolean"},{"type":"object","additionalProperties":true},{"type":"array"}]}}}},"title":"Response.ErrorItem"}}},"title":"Response.ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"status":{"type":["string","integer"],"description":"The HTTP response code of the error.","examples":["400"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]},"source":{"type":"string","description":"The field or location that caused the validation error. For JSON schema validation errors, this contains the JSON path to the invalid field (e.g., 'data.name', 'request', 'data.items[0].quantity')."},"meta":{"type":"object","description":"Additional metadata associated with the error. May include arbitrary keys.","properties":{"id":{"type":"string","description":"The resource id associated with the error"},"ids":{"type":"array","items":{"type":"string","description":"The resource ids associated with the error"}},"item_ids":{"type":"array","items":{"type":"string","description":"The cart_item ids associated with the error"}},"shipping_group_id":{"type":"string","description":"The shipping group id associated with the error"},"shipping_group_ids":{"type":"array","items":{"type":"string","description":"The shipping group ids associated with the error"}},"cart_id":{"type":"string","description":"The cart id associated with the error"},"code":{"type":"string","description":"The code associated with the error."},"order_id":{"type":"string","description":"The order id associated with the error."},"sku":{"type":"string","description":"The SKU associated with the error."},"email":{"type":"string","format":"email","description":"The email address associated with the error."},"component_product_id":{"type":"string","format":"uuid","description":"The component product ID associated with the error."},"error-meta-key":{"type":"string","description":"Custom error metadata key used for additional error context (e.g., in payment rejections)."},"value":{"description":"The value associated with the error.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"boolean"},{"type":"object","additionalProperties":true},{"type":"array"}]}}}},"title":"Response.ErrorItem"}}},"title":"Response.ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"status":{"type":["string","integer"],"description":"The HTTP response code of the error.","examples":["400"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]},"source":{"type":"string","description":"The field or location that caused the validation error. For JSON schema validation errors, this contains the JSON path to the invalid field (e.g., 'data.name', 'request', 'data.items[0].quantity')."},"meta":{"type":"object","description":"Additional metadata associated with the error. May include arbitrary keys.","properties":{"id":{"type":"string","description":"The resource id associated with the error"},"ids":{"type":"array","items":{"type":"string","description":"The resource ids associated with the error"}},"item_ids":{"type":"array","items":{"type":"string","description":"The cart_item ids associated with the error"}},"shipping_group_id":{"type":"string","description":"The shipping group id associated with the error"},"shipping_group_ids":{"type":"array","items":{"type":"string","description":"The shipping group ids associated with the error"}},"cart_id":{"type":"string","description":"The cart id associated with the error"},"code":{"type":"string","description":"The code associated with the error."},"order_id":{"type":"string","description":"The order id associated with the error."},"sku":{"type":"string","description":"The SKU associated with the error."},"email":{"type":"string","format":"email","description":"The email address associated with the error."},"component_product_id":{"type":"string","format":"uuid","description":"The component product ID associated with the error."},"error-meta-key":{"type":"string","description":"Custom error metadata key used for additional error context (e.g., in payment rejections)."},"value":{"description":"The value associated with the error.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"boolean"},{"type":"object","additionalProperties":true},{"type":"array"}]}}}},"title":"Response.ErrorItem"}}},"title":"Response.ErrorResponse"}}}}}} > --- ## Add Tax Item to Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to add a tax item to a cart. :::note There is a soft limit of 5 unique tax items per cart item at any one time. ::: Request 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]}},"required":["data"],"title":"CartItemTaxesEntityResponse"},"examples":{"rateTaxItem":{"summary":"Add a rate-based tax item","value":{"data":{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2}}},"amountTaxItem":{"summary":"Add an amount-based tax item","value":{"data":{"type":"tax_item","code":"GST","jurisdiction":"AU","name":"Goods and Services Tax","amount":1000}}}}}},"required":true}} > 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]}},"required":["data"],"title":"CartItemTaxesEntityResponse"},"examples":{"rateTaxItem":{"summary":"Rate-based tax item","value":{"data":{"id":"662461ad-ddcb-4dbd-8ed7-ade9aa63b5f9","type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2}}}}}}},"201":{"description":"Created","headers":{},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","title":"Carts Items Taxes Object","description":"A tax item that can be applied to cart items or bundle components. You must specify either a rate (percentage) or an amount (fixed value), but not both.\n","oneOf":[{"title":"Tax Object (With Rate)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]}},"required":["data"],"title":"CartItemTaxesEntityResponse"},"examples":{"amountTaxItem":{"summary":"Amount-based tax item","value":{"data":{"id":"3f3b5e26-7e7e-4d2d-a3a7-5e9b1f72fabc","type":"tax_item","code":"GST","jurisdiction":"AU","name":"Goods and Services Tax","amount":1000}}}}}}},"422":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"status":{"type":["string","integer"],"description":"The HTTP response code of the error.","examples":["400"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]},"source":{"type":"string","description":"The field or location that caused the validation error. For JSON schema validation errors, this contains the JSON path to the invalid field (e.g., 'data.name', 'request', 'data.items[0].quantity')."},"meta":{"type":"object","description":"Additional metadata associated with the error. May include arbitrary keys.","properties":{"id":{"type":"string","description":"The resource id associated with the error"},"ids":{"type":"array","items":{"type":"string","description":"The resource ids associated with the error"}},"item_ids":{"type":"array","items":{"type":"string","description":"The cart_item ids associated with the error"}},"shipping_group_id":{"type":"string","description":"The shipping group id associated with the error"},"shipping_group_ids":{"type":"array","items":{"type":"string","description":"The shipping group ids associated with the error"}},"cart_id":{"type":"string","description":"The cart id associated with the error"},"code":{"type":"string","description":"The code associated with the error."},"order_id":{"type":"string","description":"The order id associated with the error."},"sku":{"type":"string","description":"The SKU associated with the error."},"email":{"type":"string","format":"email","description":"The email address associated with the error."},"component_product_id":{"type":"string","format":"uuid","description":"The component product ID associated with the error."},"error-meta-key":{"type":"string","description":"Custom error metadata key used for additional error context (e.g., in payment rejections)."},"value":{"description":"The value associated with the error.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"boolean"},{"type":"object","additionalProperties":true},{"type":"array"}]}}}},"title":"Response.ErrorItem"}}},"title":"Response.ErrorResponse"}}}}}} > --- ## Anonymize Orders import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can anonymize an order when it is fulfilled, canceled, or fully refunded. When anonymization is successful, Personal Identifiable Information such as customer details, `shipping_address`, and `billing_address` are replaced with *. Request --- ## Bulk Add Custom Discounts to Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; The default value for custom discounts on both the cart and cart items is set to 5 if this parameter is not configured in the store. To verify the custom discount limit value, call [Get all settings](/docs/api/settings/get-v-2-settings) endpoint. To increase the custom discount value, contact [Elastic Path Support team](https://support.elasticpath.com/hc/en-us). Custom discounts cannot be combined with Elastic Path promotions. If the cart already contains Elastic Path promotions, remove them before adding custom discounts. Request --- ## Bulk Add Tax Items to Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to bulk add tax items to cart items and bundle component products. :::note A cart item can only have a maximum of five tax items. A bundle component product can only have a maximum of five tax items. ::: ### Bundle Component Taxes To add tax items to bundle component products, include a `meta` object with `component_product_id` in each tax item: ```json { "data": [ { "type": "tax_item", "code": "GST", "name": "Goods and Services Tax", "rate": 0.1, "meta": { "component_product_id": "12345678-1234-5678-9012-123456789012" }, "relationships": { "item": { "data": { "type": "cart_item", "id": "cart-item-id" } } } } ] } ``` ### Errors `422 Unprocessable Entity` In this example, when `options.add_all_or_nothing` is set to `true` and if one of cart items is not found or has reached its maximum tax item limit, the following error response is returned: ```json { "status": 422, "title": "Add all or nothing.", "detail": "Add all or nothing set to (true). Could not bulk add tax items to cart." } ``` In this example, if you add more than five tax items to the same cart item, the following error response is returned: ```json { "status": 422, "title": "Tax item not added to cart item.", "detail": "Cannot exceed tax item limit of (5) on cart item.", "meta": { "id": "f88e6370-cb35-40b2-a998-c759f31dec0a" } } ``` `404` In this example, if there is a mismatch between `cart_item`/`custom_item` and the `relationships.item.data.type` specified in the bulk add tax item, the following error response is returned: ```json { "data": [], "errors": [ { "status": 404, "title": "Tax item not added to cart item.", "detail": "Mismatch between bulk tax item type(cart_item) and cart item type(custom_item).", "meta": { "id": "56aab5d1-1dd4-45ed-88ed-4d0cc396b62d" } }, { "status": 404, "title": "Tax item not added to cart item.", "detail": "Mismatch between bulk tax item type(cart_item) and cart item type(custom_item).", "meta": { "id": "56aab5d1-1dd4-45ed-88ed-4d0cc396b62d" } } ] } ``` Request 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]},{"title":"CartItemRelationship","type":"object","properties":{"relationships":{"type":"object","required":["item"],"properties":{"item":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["type","id"],"properties":{"type":{"description":"Specifies the type of item. For example, `custom_item` or `cart_item`.","type":"string","examples":["cart_item"]},"id":{"description":"Specifies the unique identifier of the `cart_item` or `custom_item` in the cart.","type":"string","format":"uuid","examples":["5601a4b1-9d13-42d3-8fb7-03b35169d1b6"]}}}}}}}}}]}},"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"status":{"type":["string","integer"],"description":"The HTTP response code of the error.","examples":["400"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]},"source":{"type":"string","description":"The field or location that caused the validation error. For JSON schema validation errors, this contains the JSON path to the invalid field (e.g., 'data.name', 'request', 'data.items[0].quantity')."},"meta":{"type":"object","description":"Additional metadata associated with the error. May include arbitrary keys.","properties":{"id":{"type":"string","description":"The resource id associated with the error"},"ids":{"type":"array","items":{"type":"string","description":"The resource ids associated with the error"}},"item_ids":{"type":"array","items":{"type":"string","description":"The cart_item ids associated with the error"}},"shipping_group_id":{"type":"string","description":"The shipping group id associated with the error"},"shipping_group_ids":{"type":"array","items":{"type":"string","description":"The shipping group ids associated with the error"}},"cart_id":{"type":"string","description":"The cart id associated with the error"},"code":{"type":"string","description":"The code associated with the error."},"order_id":{"type":"string","description":"The order id associated with the error."},"sku":{"type":"string","description":"The SKU associated with the error."},"email":{"type":"string","format":"email","description":"The email address associated with the error."},"component_product_id":{"type":"string","format":"uuid","description":"The component product ID associated with the error."},"error-meta-key":{"type":"string","description":"Custom error metadata key used for additional error context (e.g., in payment rejections)."},"value":{"description":"The value associated with the error.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"boolean"},{"type":"object","additionalProperties":true},{"type":"array"}]}}}},"title":"Response.ErrorItem"}},"options":{"title":"Add All Or Nothing Options Object","type":"object","properties":{"add_all_or_nothing":{"description":"When `true`, if an error occurs for any item, no items are added to the cart. When `false`, valid items are added to the cart and the items with errors are reported in the response. Default is `false`.","type":"boolean","examples":[false]}}}}}]},"examples":{"bulkRateTaxItems":{"summary":"Bulk add rate-based tax items to cart items","value":{"data":[{"type":"tax_item","code":"VAT","name":"Value Added Tax","jurisdiction":"UK","rate":0.2,"relationships":{"item":{"data":{"type":"cart_item","id":"5601a4b1-9d13-42d3-8fb7-03b35169d1b6"}}}}],"options":{"add_all_or_nothing":false}}},"bulkAmountTaxItems":{"summary":"Bulk add amount-based tax items to cart and custom items","value":{"data":[{"type":"tax_item","code":"GST","name":"Goods and Services Tax","jurisdiction":"AU","amount":1000,"relationships":{"item":{"data":{"type":"cart_item","id":"1a2b3c4d-5e6f-7a8b-9c0d-abcdefabcdef"}}}},{"type":"tax_item","code":"PST","name":"Provincial Sales Tax","jurisdiction":"CA-BC","amount":250,"relationships":{"item":{"data":{"type":"custom_item","id":"9f8e7d6c-5b4a-3210-fedc-ba9876543210"}}}}],"options":{"add_all_or_nothing":true}}},"bulkBundleComponentTaxItems":{"summary":"Bulk add tax items to bundle component products using meta","value":{"data":[{"type":"tax_item","code":"GST","name":"Goods and Services Tax","jurisdiction":"AU","rate":0.1,"meta":{"component_product_id":"12345678-1234-5678-9012-123456789012"},"relationships":{"item":{"data":{"type":"cart_item","id":"22223333-4444-5555-6666-777788889999"}}}}],"options":{"add_all_or_nothing":false}}}}}},"required":false}} > 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]},{"title":"CartItemRelationship","type":"object","properties":{"relationships":{"type":"object","required":["item"],"properties":{"item":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["type","id"],"properties":{"type":{"description":"Specifies the type of item. For example, `custom_item` or `cart_item`.","type":"string","examples":["cart_item"]},"id":{"description":"Specifies the unique identifier of the `cart_item` or `custom_item` in the cart.","type":"string","format":"uuid","examples":["5601a4b1-9d13-42d3-8fb7-03b35169d1b6"]}}}}}}}}}]}},"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"status":{"type":["string","integer"],"description":"The HTTP response code of the error.","examples":["400"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]},"source":{"type":"string","description":"The field or location that caused the validation error. For JSON schema validation errors, this contains the JSON path to the invalid field (e.g., 'data.name', 'request', 'data.items[0].quantity')."},"meta":{"type":"object","description":"Additional metadata associated with the error. May include arbitrary keys.","properties":{"id":{"type":"string","description":"The resource id associated with the error"},"ids":{"type":"array","items":{"type":"string","description":"The resource ids associated with the error"}},"item_ids":{"type":"array","items":{"type":"string","description":"The cart_item ids associated with the error"}},"shipping_group_id":{"type":"string","description":"The shipping group id associated with the error"},"shipping_group_ids":{"type":"array","items":{"type":"string","description":"The shipping group ids associated with the error"}},"cart_id":{"type":"string","description":"The cart id associated with the error"},"code":{"type":"string","description":"The code associated with the error."},"order_id":{"type":"string","description":"The order id associated with the error."},"sku":{"type":"string","description":"The SKU associated with the error."},"email":{"type":"string","format":"email","description":"The email address associated with the error."},"component_product_id":{"type":"string","format":"uuid","description":"The component product ID associated with the error."},"error-meta-key":{"type":"string","description":"Custom error metadata key used for additional error context (e.g., in payment rejections)."},"value":{"description":"The value associated with the error.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"boolean"},{"type":"object","additionalProperties":true},{"type":"array"}]}}}},"title":"Response.ErrorItem"}},"options":{"title":"Add All Or Nothing Options Object","type":"object","properties":{"add_all_or_nothing":{"description":"When `true`, if an error occurs for any item, no items are added to the cart. When `false`, valid items are added to the cart and the items with errors are reported in the response. Default is `false`.","type":"boolean","examples":[false]}}}}}]},"examples":{"bulkAddedRateItems":{"summary":"Bulk add response with generated IDs (rate)","value":{"data":[{"id":"98c2b4de-7f33-4b3a-8f2e-8c1b2a3d4e5f","type":"tax_item","code":"VAT","name":"Value Added Tax","jurisdiction":"UK","rate":0.2,"relationships":{"item":{"data":{"type":"cart_item","id":"5601a4b1-9d13-42d3-8fb7-03b35169d1b6"}}}}]}}}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"title":"CartsBulkTaxes","type":"object","properties":{"data":{"type":"array","items":{"allOf":[{"title":"Carts Items Taxes Object","description":"A tax item that can be applied to cart items or bundle components. You must specify either a rate (percentage) or an amount (fixed value), but not both.\n","oneOf":[{"title":"Tax Object (With Rate)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]},{"title":"CartItemRelationship","type":"object","properties":{"relationships":{"type":"object","required":["item"],"properties":{"item":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["type","id"],"properties":{"type":{"description":"Specifies the type of item. For example, `custom_item` or `cart_item`.","type":"string","examples":["cart_item"]},"id":{"description":"Specifies the unique identifier of the `cart_item` or `custom_item` in the cart.","type":"string","format":"uuid","examples":["5601a4b1-9d13-42d3-8fb7-03b35169d1b6"]}}}}}}}}}]}},"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"status":{"type":["string","integer"],"description":"The HTTP response code of the error.","examples":["400"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]},"source":{"type":"string","description":"The field or location that caused the validation error. For JSON schema validation errors, this contains the JSON path to the invalid field (e.g., 'data.name', 'request', 'data.items[0].quantity')."},"meta":{"type":"object","description":"Additional metadata associated with the error. May include arbitrary keys.","properties":{"id":{"type":"string","description":"The resource id associated with the error"},"ids":{"type":"array","items":{"type":"string","description":"The resource ids associated with the error"}},"item_ids":{"type":"array","items":{"type":"string","description":"The cart_item ids associated with the error"}},"shipping_group_id":{"type":"string","description":"The shipping group id associated with the error"},"shipping_group_ids":{"type":"array","items":{"type":"string","description":"The shipping group ids associated with the error"}},"cart_id":{"type":"string","description":"The cart id associated with the error"},"code":{"type":"string","description":"The code associated with the error."},"order_id":{"type":"string","description":"The order id associated with the error."},"sku":{"type":"string","description":"The SKU associated with the error."},"email":{"type":"string","format":"email","description":"The email address associated with the error."},"component_product_id":{"type":"string","format":"uuid","description":"The component product ID associated with the error."},"error-meta-key":{"type":"string","description":"Custom error metadata key used for additional error context (e.g., in payment rejections)."},"value":{"description":"The value associated with the error.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"boolean"},{"type":"object","additionalProperties":true},{"type":"array"}]}}}},"title":"Response.ErrorItem"}},"options":{"title":"Add All Or Nothing Options Object","type":"object","properties":{"add_all_or_nothing":{"description":"When `true`, if an error occurs for any item, no items are added to the cart. When `false`, valid items are added to the cart and the items with errors are reported in the response. Default is `false`.","type":"boolean","examples":[false]}}}}}]},"examples":{"bulkAddedAmountAndComponentItems":{"summary":"Bulk add response with amount and component taxes","value":{"data":[{"id":"2b3c4d5e-6f70-4a8b-9c0d-1e2f3a4b5c6d","type":"tax_item","code":"GST","name":"Goods and Services Tax","jurisdiction":"AU","amount":1000,"relationships":{"item":{"data":{"type":"cart_item","id":"1a2b3c4d-5e6f-7a8b-9c0d-abcdefabcdef"}}}},{"id":"5e4d3c2b-1a0f-4b8a-9c0d-7f6e5d4c3b2a","type":"tax_item","code":"PST","name":"Provincial Sales Tax","jurisdiction":"CA-BC","amount":250,"relationships":{"item":{"data":{"type":"custom_item","id":"9f8e7d6c-5b4a-3210-fedc-ba9876543210"}}}}]}}}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"type":"object","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"status":{"type":["string","integer"],"description":"The HTTP response code of the error.","examples":["400"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]},"source":{"type":"string","description":"The field or location that caused the validation error. For JSON schema validation errors, this contains the JSON path to the invalid field (e.g., 'data.name', 'request', 'data.items[0].quantity')."},"meta":{"type":"object","description":"Additional metadata associated with the error. May include arbitrary keys.","properties":{"id":{"type":"string","description":"The resource id associated with the error"},"ids":{"type":"array","items":{"type":"string","description":"The resource ids associated with the error"}},"item_ids":{"type":"array","items":{"type":"string","description":"The cart_item ids associated with the error"}},"shipping_group_id":{"type":"string","description":"The shipping group id associated with the error"},"shipping_group_ids":{"type":"array","items":{"type":"string","description":"The shipping group ids associated with the error"}},"cart_id":{"type":"string","description":"The cart id associated with the error"},"code":{"type":"string","description":"The code associated with the error."},"order_id":{"type":"string","description":"The order id associated with the error."},"sku":{"type":"string","description":"The SKU associated with the error."},"email":{"type":"string","format":"email","description":"The email address associated with the error."},"component_product_id":{"type":"string","format":"uuid","description":"The component product ID associated with the error."},"error-meta-key":{"type":"string","description":"Custom error metadata key used for additional error context (e.g., in payment rejections)."},"value":{"description":"The value associated with the error.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"boolean"},{"type":"object","additionalProperties":true},{"type":"array"}]}}}},"title":"Response.ErrorItem"}}},"title":"Response.ErrorResponse"}}}}}} > --- ## Bulk Delete Custom Discounts From Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to bulk delete custom discounts from cart. Request --- ## Bulk Delete Tax Items from Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to bulk delete all tax items from all cart items and bundle component products in the cart. :::warning This operation will remove ALL tax items from: - All cart items in the cart - All bundle component products within bundle cart items ::: ### Behavior - Removes all tax items from every cart item - Removes all tax items from every component product in bundle cart items - If no tax items exist anywhere in the cart, returns a 404 error ### Errors `404 Not Found` If no tax items exist in the cart (on cart items or component products): ```json { "status": 404, "title": "Resource Not Found", "detail": "No tax items exist in the cart" } ``` Request --- ## Bulk Update Items in Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; The bulk update feature allows shoppers to update an array of items to their cart in one action, rather than updating each item one at a time. Shoppers can update quantity and shipping group details in bulk requests. This minimizes the time for shoppers while updating items to their cart. Shoppers can even update multiple items with the same or different shipping groups to their cart. When you update multiple items that qualify for free gifts in the cart, the corresponding free gifts for all eligible products are also automatically updated in the cart. Request --- ## Cancel a Transaction import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to cancel or void a pending or authorized transaction. The transaction can be canceled or voided when it is in `pending` and `completed` statuses. :::caution This endpoint works only for Stripe and PayPal and does not work for manual gateway. ::: Request --- ## Capture a Transaction import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to capture a previously authorized payment. In this step, you can also pass in a custom reference, such as the payment reference from your chosen gateway. Request --- ## Cart Items Products added to a cart are referred to as a `cart_item`. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Cart Management A Cart contains the product and custom cart items that a user intends to purchase. After a Cart is ready for Checkout, you can use the [Checkout endpoint](/docs/api/carts/checkout) to convert the cart to an order. :::note - Adding, modifying, or removing any cart items, custom items, or promotions always returns the cart meta, calculated using the calculation method. This is useful to update the client with up-to-date totals. - We will automatically delete carts 7 days after they were last updated. - If you do not pass a `X-MOLTIN-CURRENCY` header specifying what currency you would like the cart to use, the products in the cart are converted to your default currency. ::: ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Cart Settings Use Cart Settings to configure cart behavior for your store, including cart expiry, custom discounts, rule promotions, deferred inventory checks, and cart visibility for admins. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Carts, Checkout, Orders Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; A cart contains a list of the products that a shopper adds to the cart while browsing your catalog. In the context of a cart, a selected product is called a cart item. A cart item identifies the product, the product price, the quantity selected, and the total price for the quantity selected. The cart displays a running total of the cost for the selected products plus the calculated tax. You can allow your shoppers to add custom text to a product when adding an item to their carts. This is useful, for example, if you have a product like a T-shirt that can be personalized. See [Add product to cart](/docs/api/carts/manage-carts#add-product-to-cart). After a shopper checks out, the cart is converted to an order, and you can manually delete the cart. If you don't delete the cart, it is purged automatically after seven days. The preview cart feature allows you to set a future date for your shopping cart and view the promotions that will be available during that time period. This feature enables you to validate your promotion settings and observe how they will be applied in the cart. See [Create a Preview Cart](/docs/api/carts/create-a-cart#preview-cart). The following diagram shows a typical cart workflow: ![Shows a cart workflow, starting from adding the first item to a cart, through cart creation and checkout](/assets/cart-workflow.png) ### Multiple Carts Buyers often make purchases based on jobs that they need to perform or outcomes they need to achieve and therefore require more than one shopping cart. For example, a corporate buyer places orders for multiple locations. Each location has a different frequency of ordering and require different products. The buyer can create one cart per location, fill the carts, and then check out the carts quickly. Similarly, shoppers can also create multiple carts for the ease of managing various shopping experiences, such as birthdays or holidays. Each cart is discrete and separate. Any updates or changes to one cart has no effect on the other carts. A cart persists, that is, it stays with the buyer or shopper even after they use the cart in a checkout. Carts remain available after a checkout. Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: URL: [https://elasticpath.com](https://elasticpath.com) License MIT --- ## Checkout API import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; When a Cart is ready for checkout, you can convert the cart to an order. The cart remains and can be modified and checked out again if required. A cart can be checked out with a customer ID, customer object, or with an account by authenticating with the `Client Credentials Token`. After a successful checkout, a response that contains the order is returned. If the cart is linked to a shipping group, the shipping group is also associated with the order after checkout. You can checkout using one of the following methods: - **Customer ID**: You can checkout a cart with an existing customer ID. - **Guest Checkout** (Checkout with Customer Object): You can checkout a cart with an associated customer name and email. - **Checkout with Account**: The shopper authenticates with the `Client Credentials` Token. - **Checkout with Account Management Authentication Token**: The shopper authenticates with the `Implicit Token` and the `EP-Account-Management-Authentication-Token`. :::note - The cart currency is set when the first item is added to the cart. - The product being added to the cart requires a price in the same currency as the other items in the cart. The API returns a 400 error if a price is not defined in the correct currency. - To ensure that a free gift is automatically applied to an order, set the promotion to automatic. The checkout process will not be successful if free gift items are out of stock. See [Errors](#errors) section. ::: :::caution - By default, carts are automatically deleted 7 days after the last update. You can change this setting by [updating cart settings](/docs/api/carts/put-v-2-settings-cart). - Your inventory is modified during checkout and payment of an order. For more information about the changes in the inventory, see the [Inventory](/docs/api/pxm/inventory/inventories-introduction) section. ::: You can pass `order_number` and `external_ref` in the checkout endpoint or when [updating an order](/docs/api/carts/update-an-order). The `order_number` is an optional, user-managed field that is used as an alternative to `order_id`. When processing transactions through Authorize.net, the `order_number` is sent instead of the `order_id`, and it will appear in the invoice number section. If no `order_number` is provided, the `order_id` is sent to Authorize.net on payment by default. There are no duplication restrictions on the `order_number` value. ### Next Steps After a cart has been converted to an Order using either of the previous methods, you most likely want to capture payment for order. See [Paying for an Order](/docs/api/carts/payments). ### Errors The following error response is returned during checkout when an eligible item is added to the cart, and the free gift is out of stock. ```json { "errors": [ { "status": 400, "title": "Insufficient stock", "detail": "There is not enough stock to add gift2 to your cart", "meta": { "id": "f2b68648-9621-45a3-aed6-1b526b0f5beb", "sku": "gift2" } } ] } ``` Request --- ## Checkout The checkout workflow ties together many of the key concepts covered in this section. When a customer initiates the checkout process, an order is created from the cart. The order is incomplete until after a successful payment is made. A complete order can be shipped and the product deducted from inventory counts. ![Checkout workflow](/assets/checkout-flow.png) ### Summary of the checkout workflow 1. Add a product to a cart. A cart and its reference number is generated. 2. Manage the cart items. For example, you might add items, remove items, and change quantities. 3. Check out the cart. An incomplete order is created. 4. Pay for an order: provide billing and shipping details, if you are a new customer. The order is now in the processing status. 5. If using a manual gateway, after you authorize and capture it, Composable Commerce considers the order complete. If you use a third-party integration supported by Composable Commerce (such as Stripe), after the third-party gateway authorizes and captures the payment, the order becomes complete. Usually capture does not occur at the same time as authorization. For more information, see the Capture section. 6. After the order is shipped, you can manually flag it as fulfilled. ### Carts When a product is added to a cart, a cart is generated together with its unique reference ID that on checkout becomes a part of the order ID. If you are using our JavaScript software development kit, generating a cart reference ID is done for you; otherwise, add a cart reference generator to your functionality. ### Promotions and custom items Optionally, apply a promotion code on a cart, or add custom_items to modify the product price (typically to handle taxes, customs, or shipping). ### Checkout You can checkout a cart with an associated customer name and email (customer object). Typically, this would be used for new customers or ones that prefer to shop as guests. Use the `customer.id` checkout option to checkout for an existing customer. After a successful checkout is completed, the response contains an order. Email addresses that either begin or end with a period, or contain consecutive periods, are considered invalid, resulting in the following error: ```json "errors": [ { "status": 400, "source": "data.customer.email", "title": "format", "detail": "Does not match format 'email'" } ] ``` ### Payments On checkout, an incomplete order is created. You can then use a third-party integration to handle your payment gateway. If the payment gateway is supported by Composable Commerce, such as Stripe, the payment is processed externally but handled internally. When a successful validation is returned, Composable Commerce flags the order as complete. If you are using a payment method not officially supported by Composable Commerce, the gateway needs to be implemented and handled manually. After the payment has been authorized and captured either through Commerce Manager or API, the status of an order becomes complete. ### Shipping The status of an order and the status of shipping are handled separately, and so an order can be complete but not shipped. Orders that have not been shipped yet have a status of unfulfilled. This flag is generated automatically by Composable Commerce when an order is created. Currently, you can only update the shipping status manually, through the API. After the order is shipped, flag its shipping status as fulfilled. ### Inventory If enabled, you can manage your stock. As such, your stock is automatically updated as soon as a product is checked out. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Confirm Order import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to confirm an order. Confirming an order finalizes it and makes it ready for processing. Request --- ## Confirm Payment import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Confirm Payment serves as a mechanism to synchronize transaction information from the third-party payment provider back to our system. This ensures that Composable Commerce accurately reflects the values from the payment provider. ### Handling 3D Secure Validations for Stripe Payments For Stripe Payments requiring 3D Secure validation, the transaction response will include the `client_parameters` object, which provides credentials to support validation of these payment requests on the payment provider's side. We recommend using the Stripe's client libraries to manage these 3D Secure validations. Once the validation succeeds, proceed with a confirmation request to sync the validated transaction into Composable Commerce and continue with the payment process. Request --- ## Create a Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Creates a cart. Call this endpoint each time a customer creates a cart. Each shopper can have multiple carts. Use the carts API to create a cart. The carts are distinct from one another. Shoppers can add different items to their carts. They can check out one of the carts without affecting the content or status of their other carts. After the shopper checks out the cart, the cart remains available to the shopper. The cart is persistent and stays with the shopper after it is used. You can create a cart to specify custom discounts. You can enable custom discounts when the `discount_settings.custom_discounts_enabled` field is set to `true`. Default is set from cart discount settings for the store. See [Update Cart Settings](/docs/api/carts/put-v-2-settings-cart). You can also create a cart when inventory checks are not performed until checkout by setting the `inventory_settings.defer_inventory_check` field to `true`. Again the default is set from cart discount settings for the store. See [Update Cart Settings](/docs/api/carts/put-v-2-settings-cart). ### Preview Cart You can set a future date for your shopping cart and view the promotions that will be available during that time period. This feature enables you to validate your promotion settings and observe how they will be applied in the cart. :::caution - Once the cart is in preview mode, you cannot revert it to a regular cart. - Carts with `snapshot_date` are same as preview carts. - You cannot checkout a cart that includes a `snapshot_date`. - To delete a promotion preview cart, use [Delete a cart](/docs/api/carts/delete-a-cart) endpoint. - The promotion preview cart has the same expiration time as a regular cart based on the store's [cart settings](/docs/api/carts/put-v-2-settings-cart). - Preview cart interactions skip inventory checks and events, allowing users to preview future carts without impacting related external systems. ::: ### Custom Attributes You can create custom attributes for the cart object to include additional information, enabling promotions that target specific cart attributes. For example: ``` "custom_attributes":{ "membership": { "type": "string", "value": "VIP" } } ``` See [adding cart custom attributes in promotions builder](/docs/commerce-manager/promotions-builder/creating-a-promotion-in-promotions-builder#adding-cart-custom-attributes) Cart custom attributes remain with the corresponding cart for the extent of its lifecycle. These custom attributes carry over to the resulting order objects on checkout and those on carts are deleted with their carts upon cart deletions. Custom attributes can be updated or removed using a PUT request. To delete specific custom attributes, simply exclude the unwanted attribute objects from the PUT request body. ### Contact Email You can attach an email to carts via the `contact.email` field. These values help identify guest shopper carts and, in the case of promotions with maximum usage settings for guest and registered shopper, track per-shopper promotion usages. See [Create Max Uses Per Shopper Promotion Codes](/docs/promotions-builder/promotions-builder-codes/create-max-use-limit-promotion-codes) For example: ``` "contact": { "email": "tester@email.com" } ``` Please note, this value is not supported for registered shopper carts (that is, carts with accounts or customers associated), as these carts already have email values associated via the shopper details. Accordingly, requests to add contact email information to registered shopper carts (and vice versa) result in error messages. ### Errors - `400 Bad Request` : This is returned when the submitted request does not adhere to the expected API contract for the endpoint. - For example, in the case of string fields, this error might indicate issues in the length or format of submitted strings. For more information about valid string fields, refer to Safe Characters section. - In the case of preview carts (those with `snapshot_date`), an error is returned for invalid actions, such as removing the preview date, setting a preview date in the past, or attempting to checkout a cart with a `snapshot_date`. Request --- ## Create an Account Cart Association import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can create associations between an account and one or more carts. After cart associations exist for an account, the account can access those carts across any device. Request --- ## Create Stripe Payment Intent for a Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; The Cart Payment Intent feature enables the creation of a Stripe Payment Intent specifically tied to a shopping cart and its subsequent order. This allows Payment Intent users to track payment details from the cart stage and seamlessly maintain consistency in payment information throughout the order stage. Using these features, you can create Payment Intents for their carts, update Payment Intents with final cart details, and synchronize Payment Intents from Stripe to Commerce. :::note - Typically, in Commerce, inventory is allocated at the time of payment initiation after an order is created. However, in the case of Cart Payment Intent, information about the payment is received only upon synchronizing the order from Stripe to Commerce. This may happen after the payment is completed. Therefore, there might be a delay between the payment made and allocation, increasing the chance of paying for items that are not in stock. - There are certain fields you can choose to set up when [creating a payment intent](https://stripe.com/docs/api/payment_intents/create). However, if you decide to update a payment intent, the available options may not be the same as those allowed while creating a payment intent. See [updating a payment intent](https://stripe.com/docs/api/payment_intents/update). ::: The following steps outline the workflow associated with the Payment Intent: 1. [Add items to cart](/docs/api/carts/manage-carts#add-custom-item-to-cart). 1. [Create a Payment Intent for the cart](/docs/api/carts/create-cart-payment-intent). The Payment Intent is created in Stripe, reflecting the cart and transaction details, including currency, amounts, payment type, and any optional Stripe details. The Payment Intent ID is generated and linked to the cart. 1. [Update a Payment Intent](/docs/carts-orders/update-cart-payment-intent). This step is optional but becomes necessary when there are changes in the cart details at the time of payment. It ensures the Payment Intent accurately reflects the current cart details when processing the payments on the front end. 1. [Checkout the cart](/docs/api/carts/checkout). An unpaid order is created, and the Payment Intent ID is linked to the order. 1. [Confirm the order](/docs/carts-orders/confirm-an-order). This is important because after checkout, it is essential to confirm the Payment Intent and synchronize it with Commerce. This results in a corresponding transaction and change in order statuses in Commerce. Additionally, the Payment Intent ID is removed from the order once it is linked via the transaction. ### Best Practices We recommend you follow these practices to maintain consistency and accuracy when using Cart Payment Intent. - After checkout, we recommend clearing the shopping cart. You can achieve this using a [Delete a cart](/docs/api/carts/delete-a-cart) endpoint or [Update a cart](/docs/api/carts/update-a-cart) to remove the Payment Intent ID. This helps to avoid potential issues where subsequent checkouts for the same cart might unintentionally use the previous Stripe Payment Intent ID. - If it is not reasonable to clear the cart immediately after checkout due to several subsequent, duplicate checkouts to the same cart, ensure that you only synchronize the Payment Intent when finalizing the order. Each order confirmation is unaware of the others, and syncing Payment Intent IDs for each confirmation can lead to duplicate transactions in Commerce. In other words, if you synchronize Payment Intents for earlier versions of a repeated checkout, you'll end up with multiple orders from the same cart, each having transactions linked to the same Payment Intent. - To pay the entire amount at once, use the [Update Cart Payment Intent](/docs/carts-orders/update-cart-payment-intent) endpoint to update the Stripe Payment Intent with the final cart details when preparing to take the payment. Doing so, ensures that the Payment Intent accurately reflects the current cart details when processing payments on the front end. We do not recommend calling the [Update Cart Payment Intent](/docs/carts-orders/update-cart-payment-intent) for each individual change in the cart, as this can lead to more requests and may slow down the front-end performance. Request --- ## Create a Customer Cart Association import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can create associations between a customer and one or more carts. After cart associations exist for a customer, the customer can access those carts across any device. Request --- ## Create a shipping group for an order import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a new shipping group for an order Request --- ## Create a new shipping group for a cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a new shipping group for a cart Request --- ## Custom Discounts With custom discounts, you can allow your shoppers to apply discounts from external services to their purchases. To apply custom discounts to carts and cart items, you need to set `custom_discounts_enabled` field to `true` in your [Cart Settings](/docs/api/carts/put-v-2-settings-cart). You cannot add custom discounts to an empty cart. :::caution - You can apply up to five custom discounts to cart and cart item. - The stores that use [simple calculation method](/guides/How-To/Carts/calculate-totals) do not support custom discounts. ::: ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Customer Cart Associations You can create associations between a customer and one or more carts. After cart associations exist for a customer, those carts are accessible across any device. You can delete associations as required. There are two ways to access the cart: with a customer token and without one. ### With a `customer` token These endpoints are for users who authenticated implicitly and require a customer token in the header to access the customer cart associations APIs. For more information, see the [Customer Token](/docs/customer-management/customer-management-api/customer-tokens) documentation. #### Cart creation Shoppers create carts and can use any of the carts that they created to check out an order. :::note You can create a cart id, name, and description for the cart. The cart requires a name. Ensure that the string length is greater than or equal to one. Use any symbol in the name and description. For cart id, ensure that you follow the guidelines for safe characters. For more information about cart id naming requirements, see [Safe Characters](/guides/Getting-Started/safe-characters). ::: ### Without a `customer` token These endpoints are for users who use the Client Credentials Token and do not require a Customer token in the header to access the customer cart associations APIs. For more information, see the [Authentication](/docs/authentication/security) documentation. This user acts as a system administrator and can call any customer cart association operations for any customer and cart. ### Error Codes You might encounter the following response codes, depending on the scenario: * `400` - `The type does not exist or is not listed as customer` - Ensure that the type is `customer` and is present. * `403` - `Cannot associate more than one customer`. * `403` - `Customer does not have the required permissions to fulfill this request`. * `403` - `Invalid json payload` - Check JSON input. The request body must be an array `[]`. If the request body is an object, the error is generated. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Delete a Cart Item import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to delete a cart item. Request --- ## Delete a Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can delete a cart, including the items, name, description, and remove all associations. ### Errors The following error message is received when you attempt to delete a cart that is associated with a customer. Before deletion, ensure that the cart is disassociated. ```json message: { errors: [ { status: 400, title: 'Last cart', detail: 'This is the last cart associated with a customer and it cannot be deleted, try disassociating instead' } ] } ```` Request --- ## Delete a Promotion via Promotion Code import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can remove promotion code from a cart if it was applied manually. This endpoint does not work if the promotion is applied automatically. Request --- ## Delete a Tax Item import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to delete a tax item. Request --- ## Delete Account Cart Association import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can delete an association between an account and a cart. Request --- ## Delete all Cart Items import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; A shopper can clean up their cart, deleting custom items, promotions, and so on, while the empty cart remains available. The cart id, name, description, and any account or customer associations persist. The shopper can continue to add items to the cart. Request --- ## Delete Cart Shipping Group import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes a shipping group from a cart. You cannot delete a shipping group that is attached to cart items. You must first remove the shipping group from all cart items before deleting the shipping group. Request --- ## Delete Custom Discount From Cart Item import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to delete custom discount from cart item. Request --- ## Delete Custom Discount From Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to delete custom discount from cart. Request --- ## Delete Customer Cart Association import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can delete an association between a customer and a cart. Request --- ## Delete Tax Item from Bundle Component import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to delete a tax item from a specific bundle component (component product) within a cart item. Request --- ## Get a Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to retrieve a specific cart. If a cart ID does not exist, a new cart will be automatically created. If the cart is associated with shipping groups, calling this endpoint displays the associated shipping group IDs in the `relationships` section. You can easily get a new or existing cart by providing the unique cart reference in the request. If the cart is associated with shipping groups, calling this endpoint displays the associated shipping group IDs in the relationships section. :::note - The default cart name is Cart. However, you can update the cart name as required. Ensure that the string length of the name is greater than or equal to one. Follow the safe character guidelines for name and description naming. For more information about cart ID naming requirements, see the [Safe Characters](/guides/Getting-Started/safe-characters) section. - Outside of the JS-SDK, we don't handle creating cart references. You need to create your own. ::: :::caution An empty cart is returned for any carts that don't currently exist. For more information about the cart items object, see [Get Cart Items](/docs/api/carts/get-cart-items). ::: ### Query parameters | Name | Required | Type | Description | |:----------|:---------|:---------|:-------------------------------------------| | `include` | Optional | `string` | Comma-delimited string of entities that can be included. The information included are `items`,`tax_items`, `custom_discounts`, or `promotions`. | Request --- ## Get a Transaction import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a transaction Request --- ## Get an Order import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to retrieve a specific order. ### Includes You can include related resources with the order response by using the `include` query parameter. | Name | Required | Type | Description | |:----------|:---------|:---------|:------------| | `include` | Optional | `string` | Comma-delimited string of entities that can be included. The included options are `items`, `tax_items`, `custom_discounts`, or `promotions`. | Request --- ## Get Cart Items import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to retrieve cart items. If the cart is associated with shipping groups, calling this endpoint displays the associated shipping group IDs. You can use this endpoint to retrieve the breakdown of cart items by promotion ID. For example, if you have Promotions Standard item discount with code *sale2024*, Rule Promotions item discount with code *sale2024*, and Rule Promotions cart discount with code *sale2024*, the `discounts.constituents` field in the response example will show the breakdown of the same promotion code used in both Promotions Standard and Rule Promotions. ```json "data": [ { "id": "98de010d-dd10-4fa5-a070-0b9bcdc72974", "type": "cart_item", "product_id": "5a4662d2-9a2b-4f6e-a215-2970db914b0c", "name": "sku1", "description": "sku1", "sku": "sku1", "slug": "sku1", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": false, "unit_price": { "amount": 10000, "currency": "USD", "includes_tax": false }, "value": { "amount": 10000, "currency": "USD", "includes_tax": false }, "discounts": [ { "amount": { "amount": -2000, "currency": "USD", "includes_tax": false }, "code": "sale2024", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44", "promotion_source": "rule-promotion", "is_cart_discount": true }, { "amount": { "amount": -1000, "currency": "USD", "includes_tax": false }, "code": "sale2024", "id": "de19a043-a6da-4bde-b896-d17e16b77e25", "promotion_source": "rule-promotion" }, { "amount": { "amount": -1000, "currency": "USD", "includes_tax": false }, "code": "sale2024", "id": "509295ee-2971-45b6-801e-95df09756989" }, { "amount": { "amount": -1000, "currency": "USD", "includes_tax": false }, "code": "sale2024", "id": "ca79e606-7ecd-41ac-9478-af4c8c28c546", "promotion_source": "rule-promotion", "is_cart_discount": true } ], "links": { "product": "https://useast.api.elasticpath.com/v2/products/5a4662d2-9a2b-4f6e-a215-2970db914b0c" }, "meta": { "display_price": { "with_tax": { "unit": { "amount": 5000, "currency": "USD", "formatted": "$50.00" }, "value": { "amount": 5000, "currency": "USD", "formatted": "$50.00" } }, "without_tax": { "unit": { "amount": 5000, "currency": "USD", "formatted": "$50.00" }, "value": { "amount": 5000, "currency": "USD", "formatted": "$50.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "discount": { "unit": { "amount": -5000, "currency": "USD", "formatted": "-$50.00" }, "value": { "amount": -5000, "currency": "USD", "formatted": "-$50.00" } }, "without_discount": { "unit": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "value": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } }, "discounts": { "sale2024": { "amount": -5000, "currency": "USD", "formatted": "-$50.00", "constituents": { "509295ee-2971-45b6-801e-95df09756989": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" }, "ca79e606-7ecd-41ac-9478-af4c8c28c546": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" }, "de19a043-a6da-4bde-b896-d17e16b77e25": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" }, "e4d929d5-f471-4317-9a86-a84a6c572b44": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" } } } } }, "timestamps": { "created_at": "2024-05-24T18:00:58Z", "updated_at": "2024-05-24T18:00:58Z" } }, "catalog_id": "09b9359f-897f-407f-89a2-702e167fe781", "catalog_source": "pim" } ``` Request --- ## Get Carts import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of carts. The carts returned depend on the authentication method used: | Authentication Method | Header | Returns | | :--- | :--- | :--- | | **Customer Token** | `X-Moltin-Customer-Token` | Carts for the specified customer. See [Customer Tokens](/docs/customer-management/customer-management-api/customer-tokens). | | **Account Token** | `EP-Account-Management-Authentication-Token` | Carts for the specified account. See [Account Management Token](/docs/api/accounts/post-v-2-account-members-tokens). | | **Client Credentials** | `Authorization: Bearer ` | All carts or only registered carts, controlled by the `show_all_carts` setting. See [Cart Settings](/docs/api/carts/put-v-2-settings-cart). | **Client Credentials Behavior:** - When `show_all_carts` is `true`: Returns all carts in the store. - When `show_all_carts` is `false`: Returns only registered carts (associated with customers or accounts). **Sorting** Carts are sorted in descending order by `updated_date`. For more information, see [Pagination](/guides/Getting-Started/pagination). Request --- ## Get all Orders import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; This endpoint returns all orders with custom flow fields. The pagination offset is set to fetch a maximum of 10,000 orders. If the store has 10,000 orders, and you fetch the orders without using filters, an error is returned. Use a filter to view orders when the order is beyond the 10,000 mark. :::note - Pass the `X-Moltin-Customer-Token` header to limit orders to a specific customer. See [Customer Tokens](/docs/customer-management/customer-management-api/customer-tokens). - Pass the `EP-Account-Management-Authentication-Token` header to limit orders to a specific account. See [Account Management Token](/docs/api/accounts/post-v-2-account-members-tokens). - You can use pagination with this resource. For more information, see [pagination](/guides/Getting-Started/pagination). ::: ### Filtering The following operators and attributes are available for filtering orders. | Attribute | Type | Operator | Example | | :--- | :--- | :--- | :--- | | `status` | `string` | `eq` | `eq(status,complete)` | | `payment` | `string` | `eq` | `eq(payment,paid)` | | `shipping` | `string` | `eq` | `eq(shipping,unfulfilled)` | | `name` (`customer.name`) | `string` | `eq` / `like` | `like(name,Brad*)` | | `email` (`customer.email`) | `string` | `eq` / `like` | `like(email,*@elasticpath.com)` | | `customer_id` | `string` | `eq` / `like` | `eq(customer_id, e5a0d684-a4af-4919-a348-f66b0b4955e0)` | | `account_id` | `string` | `eq` / `like` | `eq(account_id,3d7200c9-a9bc-4085-9822-63e80fd94a09)` | | `account_member_id` | `string` | `eq` / `like` | `eq(account_member_id,2a8a3a92-2ccd-4b2b-a7af-52d3896eaecb)` | | `contact.name` | `string` | `eq` / `like` | `eq(name,John Doe)` | | `contact.email` | `string` | `eq` / `like` | `eq(email,John Doe)` | | `shipping_postcode` | `string` | `eq` / `like` | `like(shipping_postcode,117*)` | | `billing_postcode` | `string` | `eq` / `like` | `like(billing_postcode,117*)` | | `with_tax` | `integer` | `gt`/`ge`/`lt`/`le` | `ge(with_tax,10000)` | | `without_tax` | `integer` | `gt`/`ge`/`lt`/`le` | `ge(without_tax,10000)` | | `currency` | `string` | `eq` | `eq(currency,USD)` | | `product_id` | `string` | `eq` | `eq(product_id,6837058c-ae42-46db-b3c6-7f01e0c34b40)` | | `product_sku` | `string` | `eq` | `eq(product_sku,deck-shoe-001)` | | `created_at` | `date` | `eq` / `gt` / `ge`/ `le` / `lt` | `gt(created_at,YYYY-MM-DD)` | | `updated_at` | `date` | `eq` / `gt` / `ge`/ `le`/ `lt` | `lt(updated_at,YYYY-MM-DD)` | | `external_ref` | `string` | `eq` / `like` | `like(external_ref, 16be*)` | | `order_number` | `string` | `eq` / `like` | `like(order_number, 123*)` | ### Includes You can include related resources with the order response by using the `include` query parameter. | Name | Optional | Type | Description | |:-----|:---------|:-----|:------------| | `include` | Optional | `string` | Comma-delimited string of entities that can be included. The information included are `items`, `tax_items`, `custom_discounts`, or `promotions`. | Request --- ## Get Order Items import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to retrieve order items. ### Includes You can include related resources with the order items response by using the `include` query parameter. | Name | Required | Type | Description | |:----------|:---------|:---------|:------------| | `include` | Optional | `string` | Comma-delimited string of entities that can be included. The included options are `tax_items`, `custom_discounts`, or `promotions`. | Request --- ## Retrieve all shipping groups for an order import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve all shipping groups for an order Request --- ## Get Order Transactions import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get order transactions Request --- ## Retrieve a specific shipping group for a cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve a specific shipping group for a cart Request --- ## Retrieve a specific shipping group for an order import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve a specific shipping group for an order Request --- ## Retrieve all shipping groups for a cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve all shipping groups for a cart Request --- ## Get Cart Settings by Store ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves cart settings for the specified store. Request --- ## Get Cart Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves cart settings. --- ## Add Items to Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; ### Add Product to Cart Adding a Product to Cart is the most common Cart action. If you want to add any custom products or promotions, you need to do that as a separate action. #### Dynamic Bundles A bundle is a purchasable product that is composed of a combination of two or more products that you want to sell together. You can create multiple components within a bundle. Each component can have one or more options. Each option is a product and a quantity. You can configure minimum and/or maximum values for the number of product options in a component that your shoppers can select. For example, you can enable a shopper to select 1 or more product options from a list of 10. These are called [dynamic bundles](/docs/api/pxm/products/products#dynamic-bundles). Your dynamic bundles are displayed in your published catalogs. 1. Use the configure a shopper endpoint to allow shoppers to make their selections from a bundle. 2. In the response of the configure a shopper, the `bundle_configuration` object contains the bundle selections a shopper has made. 3. In the add a product to cart request, use the `bundle_configuration` object to add the customers selections to a cart. ```json "bundle_configuration": { "selected_options": { "games": { "d7b79eb8-19d8-45ea-86ed-2324a604dd9c": 1 }, "toys": { "0192ccdd-6d33-4898-87d7-c4d87f2bf8ea": 1, "1aea6f97-f0d9-452c-b3c1-7fb5629ead82": 1 } } } ``` When a cart is checked out, the options a shopper selected are added to the order. See [order items](/docs/api/carts/get-order-items). #### Personalized Products You can allow shoppers to personalize their goods by adding custom text inputs to products directly. This feature is particularly useful for customizable items, such as personalized T-shirts or greeting cards. You can use this functionality by leveraging the `custom_inputs` attribute, and defining the details and validation rules for the custom text. First, you must configure a `custom_inputs` attribute when creating a new product or updating an existing product. Once you have defined your custom inputs on a product, you must configure the custom inputs in your orders. For example, you may sell T-shirts that can have personalized text on the front and back of the shirt. ```json { "data": { "type": "product", "attributes": { "custom_inputs": { "front": { "name": "T-Shirt Front", "validation_rules": [ { "type": "string", "options": { "max_length": 50 } } ], "required": false }, "back": { "name": "T-Shirt Back", "validation_rules": [ { "type": "string", "options": { "max_length": 50 } } ], "required": false } } } } } ``` If the same product has different `custom_inputs` attributes, then these are added as separate items in a cart. The `custom_inputs` attribute is stored in the cart item and the text for `custom_input` must not exceed 255 characters in length. When a cart is checked out, the `custom_inputs` attribute becomes part of the order. #### Limitations on Usage of `custom_inputs` with Specific Promotion Types When you add products to a cart with `custom_inputs`, there are certain limitations on usage of the `custom_inputs` with the following promotion types: - For [Free Gift Promotions](/docs/api/promotions/create-a-promotion), you can add `custom_inputs` to gift items. - For [Fixed Bundle Discount Promotions](/docs/api/promotions/create-a-promotion), the promotion applies as long as the cart contains the bundle SKUs even when there are different `custom_inputs`. - For [X for Y Discount Promotion and X for amount discount promotion](/docs/api/promotions/create-a-promotion), the promotion applies when there are two SKUs with the same `custom_inputs`. The promotion does not apply when there are different `custom_inputs` and the SKUs are in different line items. #### Stock locations When adding to a cart it is possible to specify which [stock location](/docs/api/pxm/inventory_mli/inventories-introduction?#multi-location-inventories) should be used for tracking inventory for that product by specifying its slug in `location`. This might represent the warehouse a product is shipped from or the store holding the stock in a Buy Online Pick Up In Store scenario. Each line item is restricted to a single stock location. If the same product is added with a different location then the most recently-specified location will be used for the total quantity of that line item. :::note - Any requests to add a product to cart returns the collection of cart items. - [Tax items](/docs/api/carts/tax-items) may optionally be added with the product. Only administrators with [client_credentials access tokens](/docs/api/authentication/create-an-access-token) are able to do this. If included, they replace any existing taxes on the product. - The cart currency is set when the first item is added to the cart. - The product being added to the cart requires a price in the same currency as the other items in the cart. The API returns a 400 error if a price is not defined in the correct currency. - A cart can contain a maximum of 100 unique items. Items include products, custom items, tax items, and promotions. - There are a number of actions that happen to your inventory when checking out and paying for an order. For more information, see the [Inventory](/docs/api/pxm/inventory/inventories-introduction) documentation. ::: ### Including Resources When you make an `Add Product to Cart` request to the catalog-view service, you can obtain details of the component products. If you include the optional parameter `include=component_products` in the request, the response will include details for each component product. When a bundle with selected component products is added to a cart, the cart displays both the bundle pricing and component product IDs. The response example is returned with a new field called `component_products` under `bundle_configuration`, which is a list of component products that the user has selected for dynamic bundles. | Parameter | Required | Description | |:------------------------|:-------------|:-------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. | ```json "bundle_configuration": { "selected_options": { "mixed-shirts": { "16a6cc14-6ebb-4156-9973-e6a0f92f5731": 3, "55037cc5-f382-4039-95c6-1e04ac0351d3": 2, "standard-shirts" "70f1c9d2-c580-4839-bd6c-a0a9b91d5159": 5 } }, "component_products": [ { "id": "16a6cc14-6ebb-4156-9973-e6a0f92f5731", "type": "product", "attributes": { "name": "Red T-shirt", "description": "Standard red t-shirt.", "slug": "red-t-shirt-slug", "sku": "red-t-shirt-sku", "status": "live", "commodity_type": "physical" }, "meta": { "display_price": { "without_tax": { "amount": 500, "currency": "USD", "formatted": "$5.00" } } } }, { "id": "55037cc5-f382-4039-95c6-1e04ac0351d3", "type": "product", "attributes": { "name": "Blue T-shirt", "description": "Standard blue t-shirt.", "slug": "blue-t-shirt-slug", "sku": "blue-t-shirt-sku", "status": "live", "commodity_type": "physical" }, "meta": { "display_price": { "without_tax": { "amount": 500, "currency": "USD", "formatted": "$5.00" } } } }, { "id": "70f1c9d2-c580-4839-bd6c-a0a9b91d5159", "type": "product", "attributes": { "name": "White T-shirt", "description": "Standard white t-shirt.", "slug": "white-t-shirt-slug", "sku": "white-t-shirt-sku", "status": "live", "commodity_type": "physical" }, "meta": { "display_price": { "without_tax": { "amount": 500, "currency": "USD", "formatted": "$5.00" } } } } ] } ``` See [Including Resources](https://elasticpath.dev/guides/Getting-Started/includes). ### Add Subscription to Cart To add a subscription to your cart, you need to provide the ID of the subscription offering, and the ID of the pricing option and plan within that offering that you want to subscribe to. ```json { { "data": { "id": "5b9be99f-1c94-4ddd-9718-81adab0cc3e0", "type": "subscription_item", "quantity": 1, "subscription_configuration": { "plan": "dfa31307-748c-4369-8571-709f924a0807", "pricing_option": "40010dde-2f38-489b-8b3f-14a13cbfb431" } } } ``` The price of the subscription item in the cart reflects the cost of the subscription's initial billing period. Once the cart has been checked out and the order paid for, the subscription will be automatically created in the subscriptions service. ### Add Custom Item to Cart You can add a custom item to the cart when you don't manage things like shipping, taxes and inventory in Commerce. For [Shipping Groups](/docs/ship-groups/shipping-groups/index), once you have created a [cart shipping group](/docs/ship-groups/shipping-groups/shipping-groups-api/create-cart-shipping-group), you need to link it to the cart items. This is important, because it is necessary to associate items with shipping groups in order to include shipping groups in the corresponding cart, order, and totals. :::note - Custom Cart Items are available when using [implicit access tokens](/docs/api/authentication/create-an-access-token). Ensure that you always check each order has the correct details for each item, most importantly, price. ::: ### Add Promotion to Cart You can use the Promotions API to apply discounts to your cart as a special cart item type. Any requests to add a product to cart will return a collection of cart items. There are certain limitations on usage of the `custom_inputs` attribute with some promotion types. See [Limitations on Usage of `custom_inputs` with Specific Promotion Types](/docs/api/carts/manage-carts#limitations-on-usage-of-custom_inputs-with-specific-promotion-types). To remove promotion from the cart via the promotion code, see [Delete Promotion Code from Cart](/docs/api/carts/delete-a-promotion-via-promotion-code). ### Re-order From a shopper's order history, they can add the items from a previous order into their carts. Shoppers can add items regardless of past order status, such as incomplete or not paid. For more information, see [Orders](/docs/api/carts/orders). :::note - Any requests to add an item to cart return a collection of [cart items](/docs/api/carts/cart-items). - A cart can contain a maximum of 100 unique items. Items include products, custom items, and promotions. - When a shopper creates a cart and re-orders items from an order with properties such as custom attributes, custom discounts, and payment intent ID, these properties will remain unchanged in the original cart. - Custom items do not exist in catalogs, and therefore cannot be reordered. ::: ### Merging Carts A shopper can have multiple carts, and the system may automatically merge items from an anonymous cart into the shopper's registered cart when they sign in. For example, if a shopper has an existing cart with items `A`, `B` and `C`, and later adds items `D` and `E` while not signed in, the system can merge these carts when the shopper signs in. After the carts merge, the cart contains items `A`, `B`, `C`, `D` and `E`. If any items are duplicated from the anonymous cart to the registered cart, their quantities are incremented accordingly. For example, if a shopper's existing cart with items `A`, `B` and `C`, and they later add two more `A` items and one `B` item while not signed in, the system will merge the carts when the shopper signs in. The existing cart will now contain three `A` items, two `B` items, and one `C` item. :::note When the system merges items from one cart into another cart, properties such as custom attributes, custom discounts, and payment intent ID will remain unchanged in the original cart. ::: ### Best Practices We recommend to include a unique `sku` code within the request body while adding custom items to carts. If the same `sku` is used for multiple products, they are merged into a single line item. For example, if a cart consists of the following items: - `product-1` with quantity 1 and sku code as `sku-1` - `product-2` with quantity 1 and sku code as `sku-1` - `product-3` with quantity 1 and sku code as `sku-2`. The following response is returned where it combines all products with the same sku codes into a single line item, while products with a unique sku codes are represented as separate items: ```json { "data": [ { "id": "c58760f4-8889-4719-b34d-be1f1d11ae59", "type": "custom_item", "name": "product-1", "description": "My first custom item!", "sku": "sku-1", "slug": "", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 2, "manage_stock": false, "unit_price": { "amount": 20000, "currency": "USD", "includes_tax": true }, "value": { "amount": 40000, "currency": "USD", "includes_tax": true }, "links": {}, "meta": { "display_price": { "with_tax": { "unit": { "amount": 20000, "currency": "USD", "formatted": "$200.00" }, "value": { "amount": 40000, "currency": "USD", "formatted": "$400.00" } }, "without_tax": { "unit": { "amount": 20000, "currency": "USD", "formatted": "$200.00" }, "value": { "amount": 40000, "currency": "USD", "formatted": "$400.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "discount": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "without_discount": { "unit": { "amount": 20000, "currency": "USD", "formatted": "$200.00" }, "value": { "amount": 40000, "currency": "USD", "formatted": "$400.00" } } }, "timestamps": { "created_at": "2023-05-02T16:28:11Z", "updated_at": "2023-05-02T16:28:18Z" } } ] ``` Request --- ## Orders An Order is created through the [checkout](/docs/api/carts/checkout) endpoint within the Carts API. An order is created after a customer checks out their cart. On creation, the order is marked unpaid. The customer is prompted for a shipping address, a billing address, and a payment method. After the order is successfully paid, you can trigger an inventory process and a shipping process. You can keep a history of orders associated with the customer account. ### Reorder A re-order is when a shopper copies items from a previous order from their order history into a cart of their choice. If a shopper re-orders to an empty cart, the same quantities as the past order are applied. If the shopper re-orders to an existing cart, and orders the same item, the quantity increases. If an item is out of stock, the item is not added to the cart, and the shopper sees an insufficient stock error. The tax for the items in a re-order is not applied. For more information, see [Tax Items](/docs/api/carts/tax-items). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Payments import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Depending on the payment gateway, you may have access to different transaction types such as capturing funds immediately or authorizing them for later. For more information, see [Payments](/docs/api/carts/payments). The following types of payment methods are available depending on the payment gateway: - `purchase`: This is the simplest method. The gateway attempts to charge the customer immediately. - `authorize`: This method authorizes a payment so that funds can be captured later, for example, when an item is dispatched or restocked. - `purchase_setup`: This method prepares the system for a purchase by verifying payment details without actually charging the customer. For example, a customer adds items to their cart and proceeds to checkout. Before finalizing the purchase, the system runs `purchase_setup` to confirm all payment details, but no funds are transferred until the customer confirms the order. - `authorize_setup`: This method prepares the system for an authorization-only transaction. This process holds the necessary funds but does not transfer them, ensuring that the customer has sufficient balance for the transaction. It sets up the conditions for a future capture of the authorized funds. For example, a customer places a pre-order for a product that will ship in two weeks. The merchant uses `authorize_setup` to prepare for the payment authorization. This holds the customer's funds to ensure they can cover the purchase but waits to capture the payment until the product ships. This ensures that payment is secured but not collected prematurely. :::note Split payments can be performed using any methods for any gateway. - You can partially pay funds using `purchase` method. The gateway attempts to charge the customer immediately, and the payment status for an order will show `partially_paid` - You can partially pay for an order using `authorize` method where the order will be marked as `partially_authorized`. The transaction must be completed for the order status to be `partially_authorized`. - A `purchase_setup` method allows verification of payment details for partial payments without transferring funds until the customer confirms the full order. - An `authorize_setup` method can be used to hold a partial amount of the total funds, ensuring the customer has enough balance for a future capture. Until a payment is made neither `purchase_setup` nor `authorize_setup` affects the payment statuses, and the order remains unpaid. For more information about order and payment statuses for split payments, see [Split payments](/docs/api/payments/payment-gateways-introduction#split-payments). ::: Request --- ## Payments(Carts) When you [checkout](/docs/api/carts/checkout) a [cart](/docs/api/carts/cart-management), an unpaid [order](/docs/api/carts/orders) is returned. You can process the payment for the order though a payment gateway. :::note - You need to configure and enable a payment gateway before you can accept payments for orders. - Configure your store to use [Manual Gateway](/docs/api/payments/update-manual-gateway) to process payments if the order total is zero or the payment is through non-supported payment providers. - There are a number of actions that happen to your inventory when checking out and paying for an order. For more information, see [Inventory](/docs/api/pxm/inventory/inventories-introduction). - We recommend to wait until the payment confirmation process is fully completed before proceeding with any additional updates to the order. Making simultaneous updates to the same entity immediately after payment confirmation can lead to a race condition. To learn more information on handling parallel calls to API objects, see [Parallel Calls to API Objects](/guides/Getting-Started/api-contract#parallel-calls-to-api-objects). ::: ### Payment Methods Depending on the chosen gateway, you may or may not have access to capture funds immediately or authorize for later payment. To make a partial payment in Postman through any payment gateway, specify the desired payment amount in the amount field within the request body. To learn about Split Payments, see the [Split Payments](/docs/api/payments/payment-gateways-introduction#split-payments) section. #### Purchase The simplest method is purchase. The gateway attempts to charge the customer immediately, and the result of the attempt is returned. You can partially pay funds using purchase method. The gateway attempts to charge the customer immediately, and the payment status for an order shows `partially_paid`. When you Get an order, you can see the following fields in the `meta` object: - `balance_owing`: Specifies the outstanding funds required to complete an order. It considers all complete or pending transactions, including authorized, paid, and captured transactions. (`balance_owing` = order total - `authorized` amount - `paid` amount). - `paid`: Specifies the total amount of purchased or captured transactions. - `authorized`: Specifies the total amount of completed or pending authorized transactions for an order. #### Authorize You can `authorize` a payment so funds can later be captured when an item is dispatched or restocked. You can partially pay for an order using `authorize` payment method so that the order is `partially_authorized`. The transaction must be complete for the order status to be `partially_authorized`. For more information about order and payment statuses for split payments, see [Split Payments](/docs/api/payments/payment-gateways-introduction#split-payments). #### Capture After authorizing a transaction, you have to capture the authorized funds. :::note We recommend capturing payments several hours to days after the authorization to mitigate risks of fraud and chargebacks. When you sell digital goods that are delivered immediately, we recommend using a single purchase call instead of separate authorize and capture calls. ::: After the payment is `partially_authorized`, you must `capture` the authorized transaction later. Once you capture the authorized transactions, the order payment status will change to `partially_paid`. #### Refunds You can use either the Refund through Composable Commerce or use the Mark as Refunded capability, or a combination of both capabilities. For more information about refund for split payments, see [Refund a Payment](/docs/api/carts/refund-a-transaction). #### Refund through Composable Commerce You can start a full or partial refund to a supported payment provider directly from Commerce Manager or the API. When you start the refund process, the refund request is sent to the payment gateway. You no longer have to log on to your payment gateway's console to process the refund. When you process a refund, use the refund endpoint to pass the refund amount. If you don't pass an amount, the refund is processed as Mark as refunded. For more information, see the Mark as Refunded section. Each time a partial refund is triggered, the transaction.updated event is generated and updated with refunded.amount. The `order.updated` event is also triggered. The `order.refunded` event generates when the full amount is refunded. #### Mark as Refunded You can use your payment gateway's console to process a refund. Process the refund first in the payment gateway and then use the **Mark as Refunded** capability in Composable Commerce to complete the process. When an order is **Marked as refunded**, the payment status `order.payment.status` is set to `refunded`. In this case, the `order.updated`, `transaction.updated` and `order.refunded` events are generated. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Update a shipping group for an order import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a shipping group for an order Request --- ## Update Cart Settings by Store ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can modify the cart expiry settings to set it to any number of days up to 365. Any existing carts default to the expiry of 7 days. To update cart settings in Commerce Manager, see [Updating Cart setting](/docs/commerce-manager/settings/general-settings#updating-cart-settings). With update cart settings endpoint, you can: - Enable or disable custom discounts by setting the `custom_discounts_enabled` field to `true`. This allows you to activate your custom discounts from external services. By default, this setting is determined by the cart settings configured for the store. - Enable or disable the use of rule promotions within the cart. You can apply this setting either at the store level using the update cart setting endpoint or individually to a specific cart using the [update a cart](/docs/api/carts/update-a-cart) endpoint. - Enable or disable deferred inventory checks by setting `defer_inventory_check` to `true`. When set, stock levels are not verified for products in a cart until checkout. - Control whether admins can see all carts or only shopper-associated carts by setting `show_all_carts` to `true` or `false`. - Enable or disable location-based item separation by setting `separate_items_by_location` to `true`. When enabled, cart items with the same SKU but different locations are kept as separate line items instead of being merged. :::note Custom discounts and rule promotions can both be enabled for a store at the same time, for example, while transitioning from one promotion system to the other. However, an individual cart can only contain one type of discount at a time. A cart that contains custom discounts rejects Elastic Path promotions, and a cart that contains Elastic Path promotions rejects custom discounts, until the existing discounts are removed. ::: Request --- ## Update Cart Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can modify the cart expiry settings to set it to any number of days up to 365. Any existing carts default to the expiry of 7 days. To update cart settings in Commerce Manager, see [Updating Cart setting](/docs/commerce-manager/settings/general-settings#updating-cart-settings). With update cart settings endpoint, you can: - Enable or disable custom discounts by setting the `custom_discounts_enabled` field to `true`. This allows you to activate your custom discounts from external services. By default, this setting is determined by the cart settings configured for the store. - Enable or disable the use of rule promotions within the cart. You can apply this setting either at the store level using the update cart setting endpoint or individually to a specific cart using the [update a cart](/docs/api/carts/update-a-cart) endpoint. - Enable or disable deferred inventory checks by setting `defer_inventory_check` to `true`. When set, stock levels are not verified for products in a cart until checkout. - Control whether admins can see all carts or only shopper-associated carts by setting `show_all_carts` to `true` or `false`. - Enable or disable location-based item separation by setting `separate_items_by_location` to `true`. When enabled, cart items with the same SKU but different locations are kept as separate line items instead of being merged. :::note Custom discounts and rule promotions can both be enabled for a store at the same time, for example, while transitioning from one promotion system to the other. However, an individual cart can only contain one type of discount at a time. A cart that contains custom discounts rejects Elastic Path promotions, and a cart that contains Elastic Path promotions rejects custom discounts, until the existing discounts are removed. ::: Request --- ## Refund a Transaction import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; There are two ways to refund; through your payment gateway and mark it refunded in Commerce Manager, or directly through Commerce Manager or API. * Mark as Refunded: You can manually mark a transaction as refunded. Before you can mark the order as refunded, you need to handle the actual refund on your side with your payment provider. Mark as Refunded is a full refund made to the transaction. * Refund through Composable Commerce: You can process a full or partial refund to a supported payment provider directly from Commerce Manager or API by providing the refund amount. When you start the refund process, the request is directly sent to the payment gateway. :::caution If you use manual gateway for partial or full refund, you need to handle the actual refund on your side with your payment provider. ::: Request --- ## Tax Items Taxes differ by country and can differ within the country by region, state, or province. Each jurisdiction has a unique tax code and rate. If your store serves many jurisdictions, integrate a third-party tax generator to manage taxes. If your store serves a few jurisdictions, you can use the API to define the tax codes and rates in Composable Commerce. Taxes are calculated after all promotional discounts have been applied. When calculating taxes on a cart or order, you can choose from the following methods for calculating taxes: - Simple calculation method: Taxes are calculated at the unit level and are rounded to the nearest penny for the unit. - Line calculation method: Default. Taxes are calculated at the line level and are rounded to the nearest penny for the line. For more information about calculation methods, see [Calculate cart and order totals](/guides/How-To/Carts/calculate-totals). Tax values can be either `rate` or `amount`. - `rate` - Represents the tax as a percentage in decimal form. - `amount` - Represents a tax amount. :::note Tax items can be added and removed using [client_credentials access tokens](/docs/api/authentication/create-an-access-token). Only administrators with `client-credentials` access tokens are able to manage tax items. ::: ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Update a Cart Item import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can easily update a cart item. A successful update returns the cart items. Request --- ## Update a Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Updates cart properties for the specified cartID. You can update a cart to specify custom discounts. You can enable custom discounts when the `discount_settings.custom_discounts_enabled` field is set to `true`. Default is set from cart discount settings for the store. See [Cart Settings](/docs/api/carts/put-v-2-settings-cart). You can also create a cart when inventory checks are not performed until checkout by setting the `inventory_settings.defer_inventory_check` field to `true`. Again the default is set from cart discount settings for the store. See [Update Cart Settings](/docs/api/carts/put-v-2-settings-cart). Request --- ## Update a Tax Item import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to update a tax item. To change tax value from `rate` to `amount`, set `rate` to `null`, then set `amount` value and vice versa. Request 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]}},"required":["data"],"title":"CartItemTaxesEntityResponse"},"examples":{"updateRateTaxItem":{"summary":"Update a tax item using rate","value":{"data":{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.15}}},"updateAmountTaxItem":{"summary":"Update a tax item using amount","value":{"data":{"type":"tax_item","code":"GST","jurisdiction":"AU","name":"Goods and Services Tax","amount":1500}}}}}},"required":false}} > 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]}},"required":["data"],"title":"CartItemTaxesEntityResponse"},"examples":{"updatedRateTaxItem":{"summary":"Updated tax item (rate)","value":{"data":{"id":"662461ad-ddcb-4dbd-8ed7-ade9aa63b5f9","type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.15}}}}}}}}} > --- ## Update an Order import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can only update custom data, `shipping`, `shipping_address`, and status of orders. All other settings in the order object are immutable. This endpoint allows you to: - **Update an order number and external reference**: You can update an existing order that does not have an `order_number` and `external_ref`, modify the `order_number` and `external_ref` values, or remove them by passing an empty value in the `order_number` and `external_ref` fields. - **Cancel an order**: You can cancel an order only if it has not been fulfilled. - **Fulfill an order**: You can fulfill a paid order only. :::caution You can update `shipping`, `shipping_address`, and status of an order only if the order is not fulfilled. You can use the refund API to refund an order only if the payment status is `paid`. Canceling an order does not automatically refund a payment. You must refund the orders manually. ::: :::note - This request is only accessible to client credentials token users with Seller Admin role. - Non client credentials token users cannot access this endpoint. See [Permissions](/docs/authentication/tokens/permissions). - The `order_number` will appear as the invoice number in Authorize.net transactions. ::: Request --- ## Update a Payment Intent on a Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Updates the payment information for a specific payment intent on a cart. Request --- ## Update Custom Discount For Cart Item import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to update a custom discount in your cart item. Request --- ## Update Custom Discount For Cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to update a custom discount in your cart. Request --- ## Update a shipping group for a cart import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a specific shipping group for a cart Request --- ## Update Tax Item on Bundle Component import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to update a tax item on a specific bundle component (component product) within a cart item. To change tax value from `rate` to `amount`, set `rate` to `null`, then set `amount` value and vice versa. Request 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]}},"required":["data"],"title":"CartItemTaxesEntityResponse"},"examples":{"updateRateTaxItemComponent":{"summary":"Update a bundle component tax item using rate","value":{"data":{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.18}}},"updateAmountTaxItemComponent":{"summary":"Update a bundle component tax item using amount","value":{"data":{"type":"tax_item","code":"GST","jurisdiction":"AU","name":"Goods and Services Tax","amount":1200}}}}}},"required":false}} > 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["rate"],"properties":{"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). Required when using rate-based taxation.\n","type":"number","examples":[0.2]},"amount":{"description":"The tax as an absolute amount. Not allowed when rate is specified.\n","type":"number","examples":[1000]}},"not":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number"}}}}]},{"title":"Tax Object (With Amount)","allOf":[{"type":"object","required":["type"],"properties":{"code":{"description":"A unique tax code in this jurisdiction.","type":"string"},"jurisdiction":{"description":"The relevant tax jurisdiction.","type":"string"},"name":{"description":"The name of the tax item.","type":"string"},"rate":{"description":"The tax rate as a decimal (12.5% -> 0.125). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). You must specify either `rate` or `amount`, but not both.\n","type":"number"},"type":{"description":"The type of object being returned. Use `tax_item`.","type":"string","const":"tax_item"},"id":{"description":"The unique identifier for this tax item.","type":"string","format":"uuid","readOnly":true}},"title":"CartsItemsTaxesCommon"},{"type":"object","required":["amount"],"properties":{"amount":{"description":"The tax as an absolute amount in the smallest currency unit (e.g., $10 -> 1000). Required when using amount-based taxation.\n","type":"number","examples":[1000]},"rate":{"description":"The tax rate as a decimal. Not allowed when amount is specified.\n","type":"number","examples":[0.2]}},"not":{"type":"object","required":["rate"],"properties":{"rate":{"type":"number"}}}}]}],"examples":[{"type":"tax_item","code":"VAT","jurisdiction":"UK","name":"Value Added Tax","rate":0.2},{"type":"tax_item","code":"EXCISE","jurisdiction":"US","name":"Excise Tax","amount":500}]}},"required":["data"],"title":"CartItemTaxesEntityResponse"},"examples":{"componentUpdatedAmountTaxItem":{"summary":"Updated bundle component tax item (amount)","value":{"data":{"id":"7aa2ddad-2c5b-4d9b-9ce9-3e8cff778a10","type":"tax_item","code":"GST","jurisdiction":"AU","name":"Goods and Services Tax","amount":1200}}}}}}}}} > --- ## Commerce Extensions Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Commerce Extensions is a Database as a Service (DBaaS) that allows for the creation of Custom APIs and extend the capabilities of Commerce. With Custom APIs, you can efficiently manage large data sets while benefiting from both simple and complex multidimensional filtering options. Combining Custom APIs with [Composer](/docs/composer/index) enables you to deploy custom behaviors and integrations, allowing you to implement capabilities unique to your business without having to build and host that functionality from scratch. Commerce Extensions is the next generation of Flows. Flows are not going anywhere, but going forward as we add new features, Commerce Extensions will eventually provide all the capabilities and more that Flows does. We recommend using Custom APIs for any of your new use cases. Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## Create a Custom API Entry import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a Custom API Entry Request --- ## Create a Custom API import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a Custom API Request `.\n","pattern":"^[a-z0-9_-]{1,63}$"},"api_type":{"type":"string","description":"Specifies a unique API type for this Custom API. Entries for this API will use this value for their `type` field. This field must be suffixed with `_ext` to distinguish it from built in APIs.\n","pattern":"^[a-z0-9_]{1,59}_ext$"},"allow_upserts":{"type":"boolean","description":"Controls whether upsert operations are allowed for Custom API Entries via the `PUT` method. When set to `true`, it allows the creation of new Custom API Entries using `PUT` if the record doesn't exist, and updates the existing record if it does. When `false`, `PUT` requests can only update existing entries.\n","default":false},"presentation":{"type":"object","description":"Optional presentation options for the Custom API.","properties":{"page":{"type":["string","null"],"description":"The page where this Custom API should be presented. The available values depend on the deployment and may change."},"section":{"type":["string","null"],"description":"The section within the page. Can only be set when `page` is also set.","maxLength":64}}},"relationships":{"type":"object","properties":{"parent_apis":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier for the related Custom API. When the `type` of an object is set to `api_location` then `id` must be `/v2/extensions`.\nWhen the `type` of an object is set to `custom_api`, then `id` must be that of a Custom API that results in a relationship that does not have a depth exceeding 2 and does not result in a cycle.\n","example":"652e39d8-d613-493e-8c20-fef99ad6327a"},"type":{"type":"string","description":"Specifies the type of parent relationship, can be `custom_api` or `api_location`.","enum":["custom_api","api_location"]}}}}}}},"title":"CustomAPIRelationships"}}}}},"examples":{"Create Example":{"summary":"Create a Custom API","value":{"data":{"type":"custom_api","name":"Wishlists","description":"Specifies the description for this Custom API.","slug":"wishlists","api_type":"wishlist_ext","relationships":{"parent_apis":{"data":[{"id":"652e39d8-d613-493e-8c20-fef99ad6327a","type":"custom_api"}]}}}}}}}}}} > `.\n","pattern":"^[a-z0-9_-]{1,63}$"},"api_type":{"type":"string","description":"Specifies a unique API type for this Custom API. Entries for this API will use this value for their `type` field. This field must be suffixed with `_ext` to distinguish it from built in APIs.\n","pattern":"^[a-z0-9_]{1,59}_ext$"},"allow_upserts":{"type":"boolean","description":"Controls whether upsert operations are allowed for Custom API Entries via the `PUT` method. When set to `true`, it allows the creation of new Custom API Entries using `PUT` if the record doesn't exist, and updates the existing record if it does. When `false`, `PUT` requests can only update existing entries.\n","default":false},"presentation":{"type":"object","description":"Optional presentation options for the Custom API.","properties":{"page":{"type":["string","null"],"description":"The page where this Custom API should be presented. The available values depend on the deployment and may change."},"section":{"type":["string","null"],"description":"The section within the page. Can only be set when `page` is also set."}}},"links":{"type":"object","properties":{"self":{"description":"Specifies the URI of the Custom API.","example":"/v2/settings/extensions/custom-apis/3fa85f64-5717-4562-b3fc-2c963f66afa6","type":["string","null"],"format":"uri","title":"LinkURI"}}},"meta":{"type":"object","properties":{"timestamps":{"type":"object","properties":{"created_at":{"type":"string","description":"Specifies the date the entity is created.","example":"2017-01-10T11:41:19.244Z"},"updated_at":{"type":"string","description":"Specifies the date the entity is last updated.","example":"2017-01-10T11:41:19.244Z"}},"title":"Timestamps"}},"title":"Meta"},"relationships":{"type":"object","properties":{"parent_apis":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier for the related Custom API. When the `type` of an object is set to `api_location` then `id` must be `/v2/extensions`.\nWhen the `type` of an object is set to `custom_api`, then `id` must be that of a Custom API that results in a relationship that does not have a depth exceeding 2 and does not result in a cycle.\n","example":"652e39d8-d613-493e-8c20-fef99ad6327a"},"type":{"type":"string","description":"Specifies the type of parent relationship, can be `custom_api` or `api_location`.","enum":["custom_api","api_location"]}}}}}}},"title":"CustomAPIRelationships"}},"title":"CustomAPI"}}}}}},"400":{"description":"Bad request. The request failed validation.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Missing Name":{"summary":"Required field missing","value":"{\n \"errors\": [\n {\n \"title\": \"Bad Request\",\n \"status\": \"400\",\n \"detail\": \"The field 'name' is required.\"\n }\n ]\n}\n"}}}}},"409":{"description":"Unable to perform the operation at this time.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Duplicate Custom API":{"summary":"Duplicate Custom API","value":"{\n \"errors\": [\n {\n \"title\": \"Conflict\",\n \"status\": \"409\",\n \"detail\": \"custom_api with the given api_type already exists\"\n }\n ]\n}\n"},"Duplicate Custom Field":{"summary":"Duplicate Custom Field","value":"{\n \"errors\": [\n {\n \"title\": \"Conflict\",\n \"status\": \"409\",\n \"detail\": \"custom_field with the given slug already exists\"\n }\n ]\n}\n"}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Internal Server Error":{"summary":"Internal server error","value":"{\n \"errors\": [\n {\n \"title\": \"Internal Server Error\",\n \"status\": \"500\",\n \"detail\": \"there was a problem processing your request\"\n }\n ]\n}\n"}}}}}}} > --- ## Create a Custom Field import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a Custom Field Request --- ## Custom APIs Custom APIs allow you to extend the capabilities of Commerce. With Custom APIs, you can efficiently manage large data sets while benefiting from both simple and complex multidimensional filtering options. Combining Custom APIs with [Composer](/docs/composer/index) enables you to deploy custom behaviors and integrations, allowing you to implement capabilities unique to your business without having to build and host that functionality from scratch. A Custom API is composed of one or more [Custom Fields](/docs/api/commerce-extensions/custom-fields) and allows you to create [Entries](/docs/api/commerce-extensions/custom-api-entries). In database terms, a Custom API can be thought of as a table, with fields representing the columns of the table, and entries serving as the database records. ## Custom APIs vs Non-Core Flows Custom APIs are the next generation of Non-Core Flows. Here is a comparison of current features of Non-Core Flows and Custom APIs. This will be updated as we release more capabilities. | Feature | Non-Core Flows | Commerce Extensions | |---------------------------------------------------------------------------------------------------------------------------|----------------|----------------------------------------------------------------| | Build new APIs | ✅ | ✅ | | Access Level | Implicit | [Customizable](/docs/api/permissions/custom-api-role-policies) | | [Filtering](/docs/api/commerce-extensions/list-custom-api-entries#filtering) | ⛔️ | ✅ | | [Sorting](/docs/api/commerce-extensions/list-custom-api-entries#sorting) | ⛔️ | ✅ | | [Events](/docs/api/commerce-extensions/custom-api-entries#events) | ⛔️ | ✅ | | [Conditional Updates](/guides/How-To/commerce-extensions/create-a-multilocation-inventories-resource#conditional-updates) | ⛔️ | ✅ | The [Custom Fields Overview](/docs/api/commerce-extensions/custom-fields) lists the comparison of different types and validation available in Custom APIs vs Non-Core Flows. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Custom API Entries A **Custom API Entry** is a specific instance of a resource, such as a single wishlist in a Custom API for wishlists. Custom API Entries can be accessed in two different ways, via the **extension** endpoint, or the **settings** endpoint: * Extension Endpoint: `/v2/extensions/{custom-api-slug}` - This is the primary endpoint created for use. Most clients should use this endpoint as it adheres to the semantics of the configuration. Retrieve the [OpenAPI Specifications](/docs/api/commerce-extensions/get-open-api-specification) to learn how to interact with this endpoint. * Settings Endpoint: `/v2/settings/extensions/custom-apis/{custom-api-id}/entries/` - This endpoint should only be used in cases where you want to interact with your Custom APIs in a generic way in an admin capacity. Currently, the distinction between these endpoints is minimal. The extension endpoint uses a slug in the URL path, and the settings endpoint uses an ID. For most use cases involving the new Custom API, we recommend using the extension endpoint. Conceptually, the settings endpoint is analogous to reflection in most programming languages. You use it when you want to operate in a generic way. For example, we used the settings endpoint to build Commerce Manager. Another example is if you need to import and export various types of data from CSV files. Instead of writing multiple scripts for different extension endpoints, you can write one script that operates on the settings endpoint. ## Events You can integrate Commerce Extensions with your external systems by observing the appropriate events. For more information, see [Integrations](/docs/api/integrations/integrations-introduction). Given you have a Custom API with `api_type` of `wishlist_ext` and you want to perform additional processing when an action is taken, like when a wishlist is created: ```bash curl -X POST https://useast.api.elasticpath.com/v2/extensions/wishlists \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $ { "data": { "type": "wishlist_ext", "name": "My Wishlist", "items_count": 0, "keep_purchased": false } } ``` When you [create an integration](/docs/api/integrations/create-integration) with `wishlist_ext.created` in `observes` field. Then the configured `webhook` or `aws_sqs` will receive the appropriate message. You can configure integrations to observe the following events for your Custom API Entries: * Created * Updated * Deleted ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Custom Fields A Custom Field represents a single field of data (for example a Product Rating). A Custom API is composed of one or more Custom Fields. Here is a comparison of different types and validation available in Custom APIs vs Non-Core Flows. | Feature | Non-Core Flows | Commerce Extensions | |-----------------------------------------------|----------------|--------------------------------------------| | Data Type: String | ✅ | ✅ | | Data Type: Integer | ✅ | ✅ | | Data Type: Float | ✅ | ✅ | | Data Type: Boolean | ✅ | ✅ | | Data Type: List | ⛔ | ✅ | | Data Type: Any | ⛔ | ✅ | | Data Type: Date & Time | ✅ | ✅ Replaced by Regex Validation (See Below) | | Data Type: One To Many | ✅ | Planned | | Validation: Regular Expression | ⛔️ | ✅ | | Validation: Slug/Email | ✅ | ✅ Replaced by Regex Validation (See Below) | | Validation: Min/Max Value | ✅ | ✅ | | Validation: Enum(String) | ✅ | ✅ Replaced by Regex validation (See Below) | | Validation: Enum(Float/Integer) | ✅ | ⛔️ | | Validation: Allow null values | ⛔ | ✅ | | Validation: Unique(String) | ⛔ | ✅ | | Validation: Unique Case Insensitivity(String) | ⛔ | ✅ | | Validation: Immutable | ⛔ | ✅ | ## Validation When [creating](/docs/api/commerce-extensions/create-a-custom-field#request) or [updating](/docs/api/commerce-extensions/update-a-custom-field#request) a Custom Field, `validation` can be used to limit the values that may be stored in the corresponding Custom API Entry. :::note All validation changes, such as those to `allow_null_values` and any type specific rules, apply to new entries only. Existing Custom API Entry records are unaffected until updated. ::: ### Integer Validation - `min_value`: Specifies the minimum whole number that can be stored. If set, it must be less than `max_value`. - `max_value`: Specifies the maximum whole number that can be stored. If set, it must be greater than `min_value`. sample integer validation object: ```json { "validation": { "integer": { "min_value": 0, "max_value": 32 } } } ``` Even if no validation is set, field_type `integer` only supports values between -2^53+1 and 2^53+1. This is because the JSON format doesn't guarantee that values outside this range are portable ([Source](https://datatracker.ietf.org/doc/html/rfc7159#section-6)). ### Float Validation - `min_value`: Specifies the minimum number that can be stored. If set, it must be less than `max_value`. - `max_value`: Specifies the maximum number that can be stored. If set, it must be greater than `min_value`. sample float validation object: ```json { "validation": { "float": { "min_value": 0.01, "max_value": 32.01 } } } ``` The `float` field_type cannot accurately represent some numbers and so using very small or large numbers might lose precision. We recommend that API clients use either the `integer` field_type if applicable , or the `string` data type if perfect precision or recall is required. ### String Validation - `min_length`: Specifies the minimum number of characters that can be stored. If set, it must be greater than 0 and less than `max_length`. - `max_length`: Specifies the maximum number of characters that can be stored. If set, it must be greater than 0 and `min_length`. - `regex`: An [RE2](https://github.com/google/re2/wiki/Syntax) regular expression used to restrict the specific characters that can be stored. It must be less than 1024 characters. - `unique`: Specifies whether the field must have unique constraint or not. It must be `yes` or `no`. - `unique_case_insensitivity`: Applies when `unique` is set to `yes`. It controls whether values with different cases (for example, `ABC` and `abc`) should conflict. It must be `true` or `false`. sample string validation object: ```json { "validation": { "string": { "min_length": 0, "max_length": 64, "regex": "^.+\\.(jpg|jpeg|png|gif|pdf)$", "unique": "yes" "unique_case_insensitivity": true } } } ``` Even if no validation is set, field_type `string` only supports values that are up to `65535` characters long. #### Date & Time Values With Regular Expressions While Commerce Extensions does not have a native date or time type, you can none-the-less use these values in Commerce Extensions, by using the `string` field type and `regex` validation. To ensure that ordering is handled properly you should follow the guidance in [RFC 3339 - Section 5.1 Ordering](https://www.rfc-editor.org/rfc/rfc3339.html#section-5.1), namely store the fields in order of least to most precise, and in the same timezone, this will ensure that comparison operators (e.g., `gt`) and sorting, work as expected, for example the following regex will force all values to be in seconds in UTC: `^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$` One thing to keep in mind is that some libraries, especially when dealing with sub-seconds might only display them if they are non-zero, and you will want to ensure that they are fully padded to the same length. #### Enum Values with Regular Expressions You can ensure that only some values are allowed using the regular expression `^(alpha|bravo|charlie)$`. #### Slug Values with Regular Expressions Slugs can be replaced with the regular expression `^[a-z][a-z0-9-]*$`, this will ensure that the field starts with a lower case letter, and then has lower case letters, numbers or hyphens. You can tweak this regular expression as needed to suit your needs. ### Email Validation with Regular Expressions E-mails can be tricky to validate properly, especially because many services _accept_ e-mails that are not valid, and reject e-mail addresses that are technically valid. Additionally, your own capabilities and purposes might inform your decision (e.g., if you support [i18n addresses](https://datatracker.ietf.org/doc/html/rfc6530) or don't then the set of allowed e-mails changes). ### List Validation - `min_length`: Specifies the minimum number of elements that must be in the list. - `max_length`: Specifies the maximum number of elements allowed in the list. The maximum supported value is 1000. - `allowed_type`: Specifies the primitive type that all elements in the list must be. Valid values are `string`, `integer`, `boolean`, `float`, or `any`. The default is `any`, which allows mixed types. This value cannot be changed after the field is created. sample list validation object: ```json { "validation": { "list": { "min_length": 1, "max_length": 100, "allowed_type": "string" } } } ``` ### Any Validation The `any` field type allows storing arbitrary JSON values including objects, arrays, strings, numbers, booleans, and null. When updating an entry, the `any` field value is completely replaced, not merged. Filtering is not supported on `any` fields. sample any validation object: ```json { "validation": { "any": { "allow_null_values": true, "immutable": false } } } ``` ### Null Values All Custom Fields can be configured to restrict the storage of `null` values for that field on a Custom API Entry. By default, this is `true`. sample validation object : ```json { "validation": { "boolean": { "allow_null_values": false, "immutable": false } } } ``` ### Immutable When [creating](/docs/api/commerce-extensions/create-a-custom-field#request) a Custom Field, it can be configured to be `immutable`. When set to true, the value of this field can be specified only during POST requests and cannot be modified during PUT requests. By default, this is `false`. sample validation object : ```json { "validation": { "boolean": { "immutable": false } } } ``` ## Presentation When [creating](/docs/api/commerce-extensions/create-a-custom-field#request) or [updating](/docs/api/commerce-extensions/update-a-custom-field#request) a Custom Field, `presentation` can be used to influence the layout and order of fields within Commerce Manager. It does not affect the order of keys within JSON, nor influence any behaviour outside of Commerce Manager. ## Reserved Slugs The following values cannot be used as a `slug` in a Custom Field. - slug - type - id - meta - created_at - updated_at - links - relationships - attributes - attribute - dimension - dimensions - weight - weights ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Delete a Custom API import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a Custom API Request --- ## Delete a Custom API Entry import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a Custom API Entry Request --- ## Delete a Custom Field import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a Custom Field Request --- ## Get a Custom API import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a Custom API Request `.\n","pattern":"^[a-z0-9_-]{1,63}$"},"api_type":{"type":"string","description":"Specifies a unique API type for this Custom API. Entries for this API will use this value for their `type` field. This field must be suffixed with `_ext` to distinguish it from built in APIs.\n","pattern":"^[a-z0-9_]{1,59}_ext$"},"allow_upserts":{"type":"boolean","description":"Controls whether upsert operations are allowed for Custom API Entries via the `PUT` method. When set to `true`, it allows the creation of new Custom API Entries using `PUT` if the record doesn't exist, and updates the existing record if it does. When `false`, `PUT` requests can only update existing entries.\n","default":false},"presentation":{"type":"object","description":"Optional presentation options for the Custom API.","properties":{"page":{"type":["string","null"],"description":"The page where this Custom API should be presented. The available values depend on the deployment and may change."},"section":{"type":["string","null"],"description":"The section within the page. Can only be set when `page` is also set."}}},"links":{"type":"object","properties":{"self":{"description":"Specifies the URI of the Custom API.","example":"/v2/settings/extensions/custom-apis/3fa85f64-5717-4562-b3fc-2c963f66afa6","type":["string","null"],"format":"uri","title":"LinkURI"}}},"meta":{"type":"object","properties":{"timestamps":{"type":"object","properties":{"created_at":{"type":"string","description":"Specifies the date the entity is created.","example":"2017-01-10T11:41:19.244Z"},"updated_at":{"type":"string","description":"Specifies the date the entity is last updated.","example":"2017-01-10T11:41:19.244Z"}},"title":"Timestamps"}},"title":"Meta"},"relationships":{"type":"object","properties":{"parent_apis":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier for the related Custom API. When the `type` of an object is set to `api_location` then `id` must be `/v2/extensions`.\nWhen the `type` of an object is set to `custom_api`, then `id` must be that of a Custom API that results in a relationship that does not have a depth exceeding 2 and does not result in a cycle.\n","example":"652e39d8-d613-493e-8c20-fef99ad6327a"},"type":{"type":"string","description":"Specifies the type of parent relationship, can be `custom_api` or `api_location`.","enum":["custom_api","api_location"]}}}}}}},"title":"CustomAPIRelationships"}},"title":"CustomAPI"}}}}}},"400":{"description":"Bad request. The request failed validation.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Missing Name":{"summary":"Required field missing","value":"{\n \"errors\": [\n {\n \"title\": \"Bad Request\",\n \"status\": \"400\",\n \"detail\": \"The field 'name' is required.\"\n }\n ]\n}\n"}}}}},"404":{"description":"Not found. The requested entity does not exist.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Not Found":{"summary":"Requested entity not found","value":"{\n \"errors\": [\n {\n \"title\": \"Not Found\",\n \"status\": \"404\",\n \"detail\": \"Not found\"\n }\n ]\n}\n"}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Internal Server Error":{"summary":"Internal server error","value":"{\n \"errors\": [\n {\n \"title\": \"Internal Server Error\",\n \"status\": \"500\",\n \"detail\": \"there was a problem processing your request\"\n }\n ]\n}\n"}}}}}}} > --- ## Get a Custom API Entry import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a Custom API Entry Request --- ## Get a Custom Field import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a Custom Field Request --- ## Get OpenAPI Specification import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Generates an OpenAPI specification based on the Custom APIs and Custom Fields configured for the current store. This dynamically generated specification provides typed schemas for the `/v2/extensions/` endpoints. --- ## List Custom APIs import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of Custom APIs ## Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) Custom APIs: | Attribute | Operators | Example | |---------------------|-------------------------------|-----------------------------------------------| | `id` | `lt`,`le`,`eq`,`gt`,`ge`,`in` | `eq(id,7e067539-6f6c-46e1-8c55-940031b36c6a)` | | `created_at` | `lt`,`le`,`eq`,`gt`,`ge` | `ge(created_at,2024-04-29T00:00:00.000Z)` | | `updated_at` | `lt`,`le`,`eq`,`gt`,`ge` | `le(updated_at,2024-04-29T00:00:00.000Z)` | | `api_type` | `eq`,`like`,`in` | `like(api_type,wishlist*)` | | `description` | `eq`,`like` | `like(description,*list*)` | | `name` | `eq`,`like` | `eq(name,"Wishlist")` | | `slug` | `eq`,`like`,`in` | `like(slug,*lists)` | | `presentation.page` | `ilike` | `ilike(presentation.page,Home)` | ## Sorting The following attributes are available for sorting. When specified, the results are sorted in ascending order based on the value of the field. To sort in descending order, prefix the attribute with `-`, for example, `-updated_at`. The default sort order is `created_at` in descending order. - `id` - `created_at` - `updated_at` - `api_type` - `name` - `slug` Request `.\n","pattern":"^[a-z0-9_-]{1,63}$"},"api_type":{"type":"string","description":"Specifies a unique API type for this Custom API. Entries for this API will use this value for their `type` field. This field must be suffixed with `_ext` to distinguish it from built in APIs.\n","pattern":"^[a-z0-9_]{1,59}_ext$"},"allow_upserts":{"type":"boolean","description":"Controls whether upsert operations are allowed for Custom API Entries via the `PUT` method. When set to `true`, it allows the creation of new Custom API Entries using `PUT` if the record doesn't exist, and updates the existing record if it does. When `false`, `PUT` requests can only update existing entries.\n","default":false},"presentation":{"type":"object","description":"Optional presentation options for the Custom API.","properties":{"page":{"type":["string","null"],"description":"The page where this Custom API should be presented. The available values depend on the deployment and may change."},"section":{"type":["string","null"],"description":"The section within the page. Can only be set when `page` is also set."}}},"links":{"type":"object","properties":{"self":{"description":"Specifies the URI of the Custom API.","example":"/v2/settings/extensions/custom-apis/3fa85f64-5717-4562-b3fc-2c963f66afa6","type":["string","null"],"format":"uri","title":"LinkURI"}}},"meta":{"type":"object","properties":{"timestamps":{"type":"object","properties":{"created_at":{"type":"string","description":"Specifies the date the entity is created.","example":"2017-01-10T11:41:19.244Z"},"updated_at":{"type":"string","description":"Specifies the date the entity is last updated.","example":"2017-01-10T11:41:19.244Z"}},"title":"Timestamps"}},"title":"Meta"},"relationships":{"type":"object","properties":{"parent_apis":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier for the related Custom API. When the `type` of an object is set to `api_location` then `id` must be `/v2/extensions`.\nWhen the `type` of an object is set to `custom_api`, then `id` must be that of a Custom API that results in a relationship that does not have a depth exceeding 2 and does not result in a cycle.\n","example":"652e39d8-d613-493e-8c20-fef99ad6327a"},"type":{"type":"string","description":"Specifies the type of parent relationship, can be `custom_api` or `api_location`.","enum":["custom_api","api_location"]}}}}}}},"title":"CustomAPIRelationships"}},"title":"CustomAPI"}},"meta":{"type":"object","properties":{"results":{"type":"object","properties":{"total":{"type":"integer","description":"Total number of results for the entire collection."},"total_method":{"type":"string","description":"The method used to calculate the total number results.","enum":["exact","lower_bound","observed"],"x-enumDescriptions":{"exact":"Indicates that the total is an exact count of results","lower_bound":"When there are more than 10,000 results, we stop counting at 10,000 and report that the count is a lower_bound.","observed":"Will indicate if there is at least one more result past the current page, this is the highest performing option as it doesn't require an extra call."}}}},"page":{"type":"object","properties":{"limit":{"type":"integer","description":"The maximum number of records for all pages.","example":100},"offset":{"type":"integer","description":"The current offset by number of pages.","example":0},"current":{"type":"integer","description":"The current number of pages.","example":1},"total":{"type":"integer","description":"The total number of pages.","example":1}}}},"title":"PaginationMeta"},"links":{"type":"object","properties":{"current":{"description":"Always the current page.","example":"/v2/settings/custom-apis?page[offset]=0&page[limit]=100","type":["string","null"],"format":"uri","title":"LinkURI"},"first":{"description":"Always the first page.","example":"/v2/settings/custom-apis?page[offset]=0&page[limit]=100","type":["string","null"],"format":"uri","title":"LinkURI"},"last":{"description":"Always `null` if there is only one page.","example":"/v2/settings/custom-apis?page[offset]=0&page[limit]=100","type":["string","null"],"format":"uri","title":"LinkURI"},"next":{"description":"Always `null` if there is only one page.","example":null,"type":["string","null"],"format":"uri","title":"LinkURI"},"prev":{"description":"Always `null` if on the first page.","example":null,"type":["string","null"],"format":"uri","title":"LinkURI"}},"title":"PaginationLinks"}}}}}},"400":{"description":"Bad request. The request failed validation.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Bad Filter":{"summary":"Invalid field specified for filter","value":"{\n \"errors\": [\n {\n \"detail\": \"Invalid filter: unknown field [version] specified in search filter, allowed fields are [api_type created_at description id name slug updated_at]\",\n \"status\": \"400\",\n \"title\": \"Bad Request\"\n }\n ]\n}\n"}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Internal Server Error":{"summary":"Internal server error","value":"{\n \"errors\": [\n {\n \"title\": \"Internal Server Error\",\n \"status\": \"500\",\n \"detail\": \"there was a problem processing your request\"\n }\n ]\n}\n"}}}}}}} > --- ## List Custom API Entries import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of Custom API Entries ## Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) all Custom API Entries: | Attribute | Operators | Example | |---------------|-------------------------------|-----------------------------------------------| | `id` | `lt`,`le`,`eq`,`gt`,`ge`,`in` | `eq(id,859aeba1-03c2-4822-bd4c-89afce93d7eb)` | | `created_at` | `lt`,`le`,`eq`,`gt`,`ge` | `ge(created_at,2024-04-29T00:00:00.000Z)` | | `updated_at` | `lt`,`le`,`eq`,`gt`,`ge` | `le(updated_at,2024-04-29T00:00:00.000Z)` | The following operators and attributes may be available for filtering Custom API Entries depending on how the [Custom Fields](/docs/api/commerce-extensions/create-a-custom-field) for that Custom API are configured. | Field type | Operators | |------------|-----------------------------------------------------------| | `string` | `lt`,`le`,`eq`,`gt`,`ge`,`in`,`is_null`,`like` | | `integer` | `lt`,`le`,`eq`,`gt`,`ge`,`in`,`is_null` | | `float` | `lt`,`le`,`gt`,`ge`,`in`,`is_null` | | `boolean` | `eq`,`is_null` | | `list` | `contains`,`contains_any`,`is_null`,`contains_all`(typed) | Given there is a Custom Field with `"slug": "name"` and `"field_type": "string"`. When you get all Custom API Entries with query parameter: `?filter=like(name,*wish*)`. Then you will get all Custom API Entries where `name` contains the string `wish`. :::warn For performance reasons, the `is_null` search operator will **NOT** match entries for a custom_field where the custom_entry was last updated before the custom_field existed. Updating the entry will cause the field to exist and match properly. ::: ## Sorting The following attributes are available for sorting. When specified, the results are sorted in ascending order based on the value of the field. To sort in descending order, prefix the attribute with `-`, for example, `-updated_at`. The default sort order is `created_at` in descending order. - `id` - `created_at` - `updated_at` ## Query Optimization When working with large data sets, the following practices help reduce query latency and avoid timeouts. ### Choose the right `page[total_method]` By default, every list request calculates a `lower_bound` total, which counts up to 10,000 matching records. If you only need to know whether a next page exists (for example, in an infinite-scroll UI), set `page[total_method]=observed`. This skips the full count and only checks for one record beyond the current page, which can significantly reduce response times on large data sets. | Method | Behavior | Best for | |----------------|---------------------------------------------------------------------------|--------------------------------------------| | `lower_bound` | Counts up to 10,000 records; reports exact total or indicates lower bound | Displaying a total count to users | | `observed` | Checks only if a next page exists beyond the current offset and limit | Infinite scroll, cursor-style pagination | ### Skip sorting when order doesn't matter Setting `sort=null` disables sorting entirely. If your use case does not require a specific order (for example, background sync jobs), this avoids the overhead of ordering results and can improve throughput. ### Narrow your filters Queries that filter on Custom Fields are more efficient when the filter is selective. Prefer exact-match operators (`eq`, `in`) over range or wildcard operators (`like`, `lt`/`le`/`gt`/`ge`) where possible, and combine multiple filters to reduce the result set early. Request --- ## List Custom Fields import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of Custom Fields ## Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) Custom Fields: | Attribute | Operators | Example | |---------------|-------------------------------|-----------------------------------------------| | `id` | `lt`,`le`,`eq`,`gt`,`ge`,`in` | `eq(id,859aeba1-03c2-4822-bd4c-89afce93d7eb)` | | `created_at` | `lt`,`le`,`eq`,`gt`,`ge` | `ge(created_at,2024-04-29T00:00:00.000Z)` | | `updated_at` | `lt`,`le`,`eq`,`gt`,`ge` | `le(updated_at,2024-04-29T00:00:00.000Z)` | | `description` | `eq`,`like` | `like(description,*confidential*)` | | `field_type` | `eq`,`in` | `eq(field_type,string)` | | `name` | `eq`,`like` | `eq(name,"Last Name")` | | `slug` | `eq`,`like`,`in` | `like(slug,*private*)` | ## Sorting The following attributes are available for sorting. When specified, the results are sorted in ascending order based on the value of the field. To sort in descending order, prefix the attribute with `-`, for example, `-updated_at`. The default sort order is `created_at` in descending order. - `id` - `created_at` - `updated_at` - `field_type` - `name` - `slug` Request --- ## Update a Custom API import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a Custom API Request `.\n","pattern":"^[a-z0-9_-]{1,63}$"},"allow_upserts":{"type":"boolean","description":"Controls whether upsert operations are allowed for Custom API Entries via the `PUT` method. When set to `true`, it allows the creation of new Custom API Entries using `PUT` if the record doesn't exist, and updates the existing record if it does. When `false`, `PUT` requests can only update existing entries.\n","default":false},"presentation":{"type":"object","description":"Optional presentation options for the Custom API.","properties":{"page":{"type":["string","null"],"description":"The page where this Custom API should be presented. The available values depend on the deployment and may change."},"section":{"type":["string","null"],"description":"The section within the page. Can only be set when `page` is also set.","maxLength":64}}},"relationships":{"type":"object","properties":{"parent_apis":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier for the related Custom API. When the `type` of an object is set to `api_location` then `id` must be `/v2/extensions`.\nWhen the `type` of an object is set to `custom_api`, then `id` must be that of a Custom API that results in a relationship that does not have a depth exceeding 2 and does not result in a cycle.\n","example":"652e39d8-d613-493e-8c20-fef99ad6327a"},"type":{"type":"string","description":"Specifies the type of parent relationship, can be `custom_api` or `api_location`.","enum":["custom_api","api_location"]}}}}}}},"title":"CustomAPIRelationships"}}}}},"examples":{"Update Example":{"summary":"Update a Custom API","value":{"data":{"type":"custom_api","name":"Wishlists","description":"Specifies the description for this Custom API.","slug":"wishlists","relationships":{"parent_apis":{"data":[{"id":"652e39d8-d613-493e-8c20-fef99ad6327a","type":"custom_api"}]}}}}}}}}}} > `.\n","pattern":"^[a-z0-9_-]{1,63}$"},"api_type":{"type":"string","description":"Specifies a unique API type for this Custom API. Entries for this API will use this value for their `type` field. This field must be suffixed with `_ext` to distinguish it from built in APIs.\n","pattern":"^[a-z0-9_]{1,59}_ext$"},"allow_upserts":{"type":"boolean","description":"Controls whether upsert operations are allowed for Custom API Entries via the `PUT` method. When set to `true`, it allows the creation of new Custom API Entries using `PUT` if the record doesn't exist, and updates the existing record if it does. When `false`, `PUT` requests can only update existing entries.\n","default":false},"presentation":{"type":"object","description":"Optional presentation options for the Custom API.","properties":{"page":{"type":["string","null"],"description":"The page where this Custom API should be presented. The available values depend on the deployment and may change."},"section":{"type":["string","null"],"description":"The section within the page. Can only be set when `page` is also set."}}},"links":{"type":"object","properties":{"self":{"description":"Specifies the URI of the Custom API.","example":"/v2/settings/extensions/custom-apis/3fa85f64-5717-4562-b3fc-2c963f66afa6","type":["string","null"],"format":"uri","title":"LinkURI"}}},"meta":{"type":"object","properties":{"timestamps":{"type":"object","properties":{"created_at":{"type":"string","description":"Specifies the date the entity is created.","example":"2017-01-10T11:41:19.244Z"},"updated_at":{"type":"string","description":"Specifies the date the entity is last updated.","example":"2017-01-10T11:41:19.244Z"}},"title":"Timestamps"}},"title":"Meta"},"relationships":{"type":"object","properties":{"parent_apis":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier for the related Custom API. When the `type` of an object is set to `api_location` then `id` must be `/v2/extensions`.\nWhen the `type` of an object is set to `custom_api`, then `id` must be that of a Custom API that results in a relationship that does not have a depth exceeding 2 and does not result in a cycle.\n","example":"652e39d8-d613-493e-8c20-fef99ad6327a"},"type":{"type":"string","description":"Specifies the type of parent relationship, can be `custom_api` or `api_location`.","enum":["custom_api","api_location"]}}}}}}},"title":"CustomAPIRelationships"}},"title":"CustomAPI"}}}}}},"400":{"description":"Bad request. The request failed validation.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Missing Name":{"summary":"Required field missing","value":"{\n \"errors\": [\n {\n \"title\": \"Bad Request\",\n \"status\": \"400\",\n \"detail\": \"The field 'name' is required.\"\n }\n ]\n}\n"}}}}},"404":{"description":"Not found. The requested entity does not exist.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Not Found":{"summary":"Requested entity not found","value":"{\n \"errors\": [\n {\n \"title\": \"Not Found\",\n \"status\": \"404\",\n \"detail\": \"Not found\"\n }\n ]\n}\n"}}}}},"409":{"description":"Unable to perform the operation at this time.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Duplicate Custom API":{"summary":"Duplicate Custom API","value":"{\n \"errors\": [\n {\n \"title\": \"Conflict\",\n \"status\": \"409\",\n \"detail\": \"custom_api with the given api_type already exists\"\n }\n ]\n}\n"},"Duplicate Custom Field":{"summary":"Duplicate Custom Field","value":"{\n \"errors\": [\n {\n \"title\": \"Conflict\",\n \"status\": \"409\",\n \"detail\": \"custom_field with the given slug already exists\"\n }\n ]\n}\n"}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"object","required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","format":"string","examples":["400"]},"title":{"type":"string","description":"A brief summary of the error.","examples":["Bad Request"]},"detail":{"type":"string","description":"Optional additional detail about the error.","examples":["The field 'name' is required"]}}}}},"title":"Errors"},"examples":{"Internal Server Error":{"summary":"Internal server error","value":"{\n \"errors\": [\n {\n \"title\": \"Internal Server Error\",\n \"status\": \"500\",\n \"detail\": \"there was a problem processing your request\"\n }\n ]\n}\n"}}}}}}} > --- ## Update a Custom API Entry import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a Custom API Entry Request --- ## Update a Custom Field import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a Custom Field Request --- ## Addresses Introduction(Customer-addresses) import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; The Addresses API allows you to organize customer addresses. Addresses are a sub-resource of a `customer`, a customer can have multiple addresses, such as home, work, and neighbour. You can use a customer address with an [implicit access token](/docs/api/authentication/create-an-access-token), which is recommended for client-side interactions. You can also use a [client_credentials access token](/docs/api/authentication/create-an-access-token), which is recommended for back-end interactions. Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## Customer Addresses The API to organize customer addresses. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Delete a Customer Address import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete an address for a Customer. Request --- ## Get an Customer Address import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get an address for a Customer. Request --- ## Get Customer Addresses import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get all addresses for a Customer. You can use pagination with this resource. For more information, see [pagination](/guides/Getting-Started/pagination). ### Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) addresses: | Attribute | Operators | Example | |----------------|---------------------------------|---------------------------------------| | `name` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(name,"*home*")` | | `first_name` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(first_name,"Ron*")` | | `last_name` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(last_name,"*swan*")` | | `phone_number` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(phone_number,"*555*")` | | `company_name` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(company_name,"*enterprises*")` | | `instructions` | `eq`,`in`,`like`,`ilike`,`text` | `text(instructions,"behind bin")` | | `line_1` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(line_1,"*Sunny Street*")` | | `line_2` | `eq`,`in`,`like`,`ilike`,`text` | `ilike(line_2,"*Unit*")` | | `city` | `eq`,`in`,`like`,`ilike`,`text` | `eq(city,"Sunny Town")` | | `county` | `eq`,`in`,`like`,`ilike`,`text` | `eq(county,"Sunnyville")` | | `region` | `eq`,`in`,`like`,`ilike`,`text` | `eq(region,"California")` | | `postcode` | `eq`,`in`,`like`,`ilike`,`text` | `eq(postcode,"SU33 1YY")` | | `country` | `eq`,`in`,`like`,`ilike`,`text` | `eq(country,"GB")` | Request --- ## Create a Customer Address import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create an address for a Customer. Request --- ## Update an Customer Address import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update an address for a Customer. Request --- ## Create Job import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a Job to export orders to a CSV file. Jobs automatically expire one week after creation. You must fetch the exported data before the jobs expire. Request --- ## Exporter Service API import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Use the Exporter Service API to export orders to a Comma-Separated Values (CSV) file. When you run the `export order` endpoint, a job is created. Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Get a Job File import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a link to the CSV file that contains your exported order. Request --- ## Get a Job import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the specified job. Request --- ## Get All Jobs import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can use this endpoint to display the status of your jobs. --- ## Jobs Jobs have the following characteristics: - Jobs are asynchronous. - This process is repeated until all jobs are processed. - Jobs have a different status, depending on where a job is in its lifecycle. - Jobs are processed one at a time. You can continue to send requests using endpoints that function as jobs, but those jobs are queued. In other words, Commerce looks for any jobs that have a status of PENDING and starts the job with the earliest created date. - Jobs include the data used when an endpoint is run. - Jobs report messages and/or errors to help you understand the reasons for any failed jobs. ### Job Lifecycle A job can have the following status: - PENDING - Commerce has received the request but is currently busy processing other requests. - STARTED - Commerce has started processing the job. - SUCCESS - The job has successfully completed. - FAILED - The job has failed. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Create a Field import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint creates a field. - For Product Experience Manager, this endpoint creates an attribute. Request --- ## Create a Flow import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint creates a flow. - For Product Experience Manager, this endpoint creates a template. :::caution Custom names and values prefixed with $ are not supported. ::: Request --- ## Create an Entry Relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - In Commerce, create an entry relationship to one or more resources. If any relationships already exist, the ones made in the request are added to them. - In Product Experience Manager, create an entry relationship with the product to which you want to associate the template. Request --- ## Create an Entry import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint creates an entry for a flow. - For Product Experience Manager, this endpoint creates an entry for a template. Request --- ## Delete a Field import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint deletes a field. - For Product Experience Manager, this endpoint deletes an attribute. Request --- ## Delete a Flow import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint deletes a flow. We recommend that you remove all the fields assigned to a flow before deleting a flow. - For Product Experience Manager, this endpoint deletes a template. We recommend that you remove all the attributes assigned to a template before deleting a template. Request --- ## Delete an Entry Relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - In Commerce, deletes an entry relationship to one or more resources. - In Product Experience Manager, deletes an entry relationship with the product to which you want to associate the template. Request --- ## Delete an Entry import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint deletes an entry from a flow. - For Product Experience Manager, this endpoint deletes an entry from a template. Request --- ## Entries ### Entries in Commerce Entries hold the pieces of data collected within the fields. If your flow has more than one field related to it, you see multiple field slugs. ### Entries in Product Experience Manager Entries hold the pieces of data collected within the attributes. If your template has more than one attribute related to it, you see multiple attribute slugs. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Entry Relationships ### Entry Relationships in Commerce When you create a field that uses `relationship` as a `field_type`, you update your entry values using the `Entry Relationship` endpoints. ### Entry Relationships in Product Experience Manager Once you have created your templates, you must associate them with your products using the `Entry Relationship` endpoints. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Fields With fields, you can: - in Commerce, use a field in your flows to represent single field of data (for example a `Product Rating`) to be applied to an entity - in Product Experience Manager, use an attribute in your template to attach a characteristic like `color` to a product. A field/attribute represents a single piece of data. All fields/attributes have a `field_type` (`string`, `integer`, `boolean`, `date` or `relationship`), a default value, and an optional set of validation rules. :::caution - Custom names and values prefixed with `$` are not supported. - There is a hard limit of 100 fields per flow. - You can configure default values for fields. If you choose to do so, you must ensure that your default field values comply with your validation rules. ::: #### Field/Attribute Validation Rules When creating a field/attribute, you can add validation to the values that are stored. The validation you use depends on the `field_type` of the field/attribute. Each validation rule is expressed as a validation rule object. #### `string` / `enum` Must be one of a predefined collection of strings. If you leave the field blank or enter an incorrect value then an `Invalid Value` error is displayed. | Attribute | Type | Description | | :--- | :--- | :--- | | `type` | `string` | `enum` | | `options` | `array[string]` | An array of valid string values. | ##### `string` / `email` Must be a valid email address. | Attribute | Type | Description | | :--- | :--- | :--- | | `type` | `string` | `email` | ##### `string` / `slug` Can contain only letters, numbers, hyphens and underscores. | Attribute | Type | Description | | :--- | :--- | :--- | | `type` | `string` | `slug` | ##### `integer` / `between` Must be between the two provided values. | Attribute | Type | Description | | :--- | :--- | :--- | | `type` | `string` | `enum` | | `options` | `object` | An object containing `from` and `to` integers. | ##### `integer` / `enum` Must be one of a predefined collection of integers. | Attribute | Type | Description | | :--- | :--- | :--- | | `type` | `string` | `enum` | | `options` | `array[integer]` | An array of valid integer values. | ##### `float` / `between` Must be between the two provided values. | Attribute | Type | Description | | :--- | :--- | :--- | | `type` | `string` | `enum` | | `options` | `object` | An object containing `from` and `to` floats. | ##### `float` / `enum` Must be one of a predefined collection of floats. | Attribute | Type | Description | | :--- | :--- | :--- | | `type` | `string` | `enum` | | `options` | `array[float]` | An array of valid float values. | #### `date` / `enum` Must be one of a predefined collection of dates. | Attribute | Type | Description | | :--- | :--- | :--- | | `type` | `string` | `enum` | | `options` | `array[string]` | An array of valid date values as strings \(`YYYY-MM-DD HH:MM:SS` - time is optional\). | ##### `relationship` / `one-to-many` :::caution This only applies to Commerce. You cannot use relationships in Product Experience Manager templates. ::: Allows multiple relationships to be created. | Attribute | Type | Description | | :--- | :--- | :--- | | `type` | `string` | `one-to-many` | | `to` | `string` | The entity type you are making relationships with in singular form (for example, `product`). | ##### `relationship` / `one-to-one` :::caution This only applies to Commerce. You cannot use relationships in Product Experience Manager templates. ::: Allows only a single relationships to be created on an entry. | Attribute | Type | Description | | :--- | :--- | :--- | | `type` | `string` | `one-to-one` | | `to` | `string` | The entity type you are making relationships with in singular form (for example, `customer`). | ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Flows Service Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; With flows you can extend the capabilities of Commerce and Product Experience Manager at both organization and store level, and apply Composable Commerce to almost any use case. ### Flows in Commerce You can define custom data fields for the resources that you use in your store or organization, such as adding more fields to the `customer` resource. You can also create new resources, such as a `wishlist` resource to support wishlists in your store. :::note [Custom APIs](/docs/api/commerce-extensions/custom-ap-is#custom-apis-vs-non-core-flows) are the next generation of Non-Core Flows. Flows are not going anywhere, but Custom APIs offer enhanced capabilities. We recommend using Custom APIs for any of your new use cases. ::: :::caution - In an organization, not all resources are available. See [**Extend a resource**](https://elasticpath.dev/guides/Custom%20Data/extend-any-resource) for a list of organization resources that can be extended. - If you store any sensitive Personal Identifiable Information (PII) or non-public data on your site, ensure that you do not use this data in flows to avoid potential unauthorized access to the data. For more information, see [**Permissions**](/docs/authentication/tokens/permissions). ::: ### Templates in Product Experience Manager Templates allow you to attach a specific set of attributes to your products. - You can use templates to define characteristics of your product, for example, a product specification. For example, a *Book* template might contain attributes, such as *ISBN*, *Author*, *Number of pages*, *Year Published*, or *Condition (New/Used)*. - You can use templates for Search Engine Optimization (SEO). When you assign template attributes such as, *care instructions* or *fabric*, to a shirt and a shopper searches for a specific item, attributes help stores to return the products that match the search criteria. For example, when a shopper searches for a large blue shirt, all shirts that are large and blue are returned in the search result. Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Flows ### Flows in Commerce There are two scenarios for using flows: - Extend an existing resource, such as customers and orders. - Create a new resource, such as a blog, wishlist, or customer review. #### Extend an existing resource The most common usage of the Flows API is to extend existing resources, such as `customers` and `orders`. These types of resources are called core flows and are handled differently than non-core flows. See [**Core and non-core flows**](#core-and-non-core-flows). For example, you can extend the `customer` resource to store custom data, such as a `user_profile` field for customers. Or you might want to add an `age` field to store a customer's age. Extending a resource applies only to core flows. When creating a new flow, make sure the `slug` matches that of a core resource listed in the following table. | Flow slug | Description | Availability Level | |:--------------------------------------------|:-------------------------------| :---| | `accounts` | Extend the [`account`](/docs/api/accounts/account-management-introduction) object. | Store | | `account-members` | Extend the [`account-members`](/docs/api/accounts/account-members) object. | Store | | `account-memberships` | Extend the [`account-membership`](/docs/api/accounts/account-membership) object. | Store | | `addresses` | Extend the [`address`](/docs/api/addresses/account-addresses) object. | Store | | `authentication-realms` | Extend the [`authentication-realms`](/docs/api/single-sign-on/authentication-realms) object. | Store | | `carts` | Extend the [`carts`](/docs/api/carts/carts-checkout-orders-introduction) object. | Organization/Store | | `cart_items` | Extend the [`cart_item`](/docs/api/carts/cart-items) object. | Organization/Store | | `customers` | Extend the [`customer`](/docs/customer-management/customer-management-api/customer-management-api-overview) object. **Note**: Please use Account Management for all new frontend experiences. | n/a | | `oidc-profiles` | Extend the [`oidc-profiles`](/docs/api/single-sign-on/oidc-profiles) object. | Store | | `order_items` | Extend the [`order_item`](/docs/api/carts/get-order-items) object. | Organization/Store | | `orders` | Extend the [`order`](/docs/api/carts/orders) object. | Organization/Store | | `password-profiles` | Extend the [`password-profiles`](/docs/api/single-sign-on/password-profiles) object. | Store | | `products` | Extend the [`product`](/docs/api/pxm/products/products) object. | Store | | `promotions` | Extend the [`promotion`](/docs/api/promotions/promotions-standard-introduction) object. | Store | | `rule-promotions` | Extend the [`rule-promotion`](/docs/api/promotions-builder/create-rule-promotion) object. | Store | | `user-authentication-info` | Extend the [`user-authentication-info`](/docs/api/single-sign-on/user-authentication-infos) object. | Store | | `user-authentication-oidc-profile-info` | Extend the [`user-authentication-oidc-profile-info`](/docs/api/single-sign-on/user-authentication-oidc-profile-infos) object. | Store | | `user-authentication-password-profile-info` | Extend the [`user-authentication-password-profile-info`](/docs/api/single-sign-on/user-authentication-password-profile-infos) object. | Store | | `catalogs` | Extend the [`catalog`](/docs/api/pxm/catalog/catalogs) object. It will not extend the [`catalog-release`](/docs/api/pxm/catalog/releases) object. | Store | | `shipping-groups` | Extend the [`shipping-group`](/docs/api/carts/create-shipping-group) object. | Store | #### Create a new resource You can create new resources to support product reviews, wish lists, blog articles, staff profile pages, and many more. These non-core flows are referred to as custom flows. See [**Core and non-core flows**](#core-and-non-core-flows). :::note [Custom APIs](/docs/api/commerce-extensions/custom-ap-is#custom-apis-vs-non-core-flows) are the next generation of Non-Core Flows. Flows are not going anywhere, but Custom APIs offer enhanced capabilities. We recommend using Custom APIs for any of your new use cases. ::: #### Core and non-core flows The following table describes the differences between core and non-core flows: | Core Flows | Non-core Flows | |:--------------------------------------------------------------|:-------------| | Extend an existing resource. | Create a new resource. | | Entries managed automatically by Commerce. | Create and manage entries manually. | | Requests are sent to the `fields` endpoint. | Requests are sent to the `entries` endpoint. | :::caution You cannot delete core flows after creating them with the API or Commerce Manager. ::: #### Flows taxonomy Fields and entries are an integral part of flows. A flow describes a collection of fields. A field represents a single field of data. An entry is a specific instance of a flow, and is associated with a specific instance of an entity, such as a single customer. Entries for core flows (existing resources) are managed automatically for you. In database terms, you can think of flows as tables, fields as columns, and entries as database records. ### Templates in Product Experience Manager Templates allow you to attach a specific set of attributes to your products. - You can use templates to define characteristics of your products. - You can use templates for Search Engine Optimization (SEO). #### Template Taxonomy Attributes and entries are integral to templates. A template describes a collection of attributes. An attribute represents a single characteristic, like color. An entry is a specific instance of an attribute, for example, blue, and is associated with a specific product. A template is exactly the same as a flow except it has a different naming convention. The name of a template is in the format **products(*slug*)** where *slug* is the slug of a template. #### Associating templates with products Once you have created your template, and [**associated**](/docs/api/flows/create-an-entry-relationship) the temp with a product in Product Experience Manager, it becomes a template. For example, if you create a template with a slug of `SizeGuide` then the template name is **products(SizeGuide)**. You can then [**associate**](/docs/api/flows/create-an-entry-relationship) this template to all clothing products in your store and the slug is included in all the responses that contain products. You can create product templates for both organization and store. In addition, stores can use organization templates for store-level products. For more information about adding attributes, see [**Fields**](/docs/api/flows/fields). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Get a Field import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint retrieves a field. - For Product Experience Manager, this endpoint retrieves an attribute. Request --- ## Get a Flow import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint retrieves a flow. - For Product Experience Manager, this endpoint retrieves a template. Request --- ## Get all Entries import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint retrieves all entries for a flow. - For Product Experience Manager, this endpoint retrieves all entries for a template. Request --- ## Get all Fields by Flow import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get all Fields by Flow Request --- ## Get all Fields import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint retrieves all fields in a flow. - For Product Experience Manager, this endpoint retrieves all attributes in a template. Request --- ## Get all Flows import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint retrieves a list of flows. - For Product Experience Manager, this endpoint retrieves a list of templates. Request --- ## Get an Entry import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint retrieves an entry from a flow. - For Product Experience Manager, this endpoint retrieves an entry from a template. Request --- ## Update a Field import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint updates a field. - For Product Experience Manager, this endpoint updates an attribute. Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the field/attribute is not updated. Request --- ## Update a Flow import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint updates a flow. - For Product Experience Manager, this endpoint updates a template. Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the flow/template is not updated. Request --- ## Update an Entry Relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - In Commerce, updates an entry relationship to one or more resources. If any relationships already exist, the ones made in the request are added to them. - In Product Experience Manager, updates an entry relationship with the product to which you want to associate the template. Request --- ## Update an Entry import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - For Commerce, this endpoint updates an entry for a flow. - For Product Experience Manager, this endpoint updates an entry for a template. Request --- ## Create an integration import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create an integration. Request --- ## Delete an integration import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes the Integration for the given UUID Request --- ## Get an integration import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the integration for the given UUID. Request --- ## Integrations Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; You can integrate Commerce with your external systems like enterprise resource planning, order management, fulfilment, and other systems, ensuring that buying is quick and easy for your shoppers. Events are actions that occur in your commerce workflow, such as a customer changing their address or an order changing status from created to paid. You can create custom functions that perform additional processing outside of Commerce, and create integrations so that when an event occurs in your store, the custom function is run. For example: - When a customer updates their address, the Customer Relationship Management system is updated with the change. - When an order status changes to paid, the affected stock in an inventory management system is reduced by the number of items in the order. Events are processed concurrently. This means that events may not be delivered in the order they are created. For example, if the status of an order is updated multiple times, the events may not be delivered in the same sequence they were updated. Integration events operate on an "at least once" delivery policy. We aim to deliver messages within 15 seconds except in cases of high load. Ensure that you design your receiving code accordingly. :::note For a list of all the events that can be used, see [Observable Events](#observable-events). ::: You can integrate Commerce with your external systems using: - Webhooks - Message Queuing Services ### Webhooks You can use Webhooks to deliver Commerce events to a configured HTTP endpoint. ### Message Queuing Services You can deliver Commerce events to messages queues through the following message queuing services: - Amazon Simple Queuing Service (SQS) - Message queuing services that support the Message Simple Text Orientated Messaging Protocol (STOMP), for example, Amazon MQ. :::note You can integrate Amazon SQS and message queuing services that support STOMP through the Integrations API. You can view the integration details in Commerce Manager > **SYSTEM** > **Store Settings** > **Webhooks**. For more information, see [Create an integration](/docs/api/integrations/create-integration). ::: ### Integration Types Commerce supports the following integration types: - Using [webhooks](/docs/api/integrations/create-integration), you can have Commerce deliver events to a configured HTTP endpoint. :::caution Webhooks that return anything other than a 2XX status code, or take more than 10 seconds to respond, are considered failed. - Using [message queuing services](#message-queuing-services), you can deliver Commerce events to a message queue. The advantages of using message queuing services over webhooks are: - A temporary failure of a webhook endpoint can result in lost events. However, if messages are on your own queue, you can leave the event on the queue to retry later. - If events take a long time to process, a webhook can timeout, but delivery to a queue is always going to take the same amount of time. ::: ### Webhooks An integration with an `integration_type` of [`webhook`](/docs/api/integrations/create-integration) delivers its events to a configured HTTP endpoint. ### Message Queuing Services Elastic Path allows you to integrate with the following message queuing services: - Amazon Simple Message Queuing Service (SQS). - Message queuing services that use Simple Text Orientated Messaging Protocol (STOMP), for example, Amazon MQ. :::caution You can integrate Amazon SQS and message queuing services that support STOMP through the Integrations API. You can view the integration details in Commerce Manager > **SYSTEM** > **Store Settings** > **Webhooks**. For more information, see [Create an integration](/docs/api/integrations/create-integration). ::: #### Amazon Simple Message Queuing Service (SQS) An integration with an `integration_type` of [`aws_sqs`](/docs/api/integrations/create-integration) delivers its events directly into the configured AWS SQS queue. These messages can be processed by any appropriate means, such as a Lambda function. For more information about creating Simple Queue Service (SQS) queues, see the [Simple Queue Service (SQS)](https://elasticpath.dev/guides/How-To/Integrations/sqs-queues) and [SQS Events with CloudFormation](https://elasticpath.dev/guides/How-To/Integrations/sqs-queues-cloudformation) sections. #### Simple Text Orientated Messaging Protocol (STOMP) An integration with the [`stomp`](/docs/api/integrations/create-integration) integration type delivers its events directly into a configured queue. Any message queuing service that uses STOMP, such as Amazon MQ, can process these messages. For more information, see the documentation provided with the message queuing service you are using. ### Webhooks The payload delivered to your webhook `url` contains information about the fired event. The payload attributes and types are defined in the following table. | Attribute | Type | Description | | :------------- | :------------------------------- | :------------------------------------------------------------------------------------------------ | | `id` | `string` | A unique ID for this event. | | `integration` | `object` | The events `integration_type` being fired. | | `triggered_by` | `string` | The [observable events](#observable-events) that triggered this event. | | `attempt` | `integer` | The number of attempts to deliver this event. | | `resources` | `string` | The resources affected by this event. This field is now deprecated. Please use `payload` instead. | | `payload` | `object` | The resources affected by this event. | :::note Store-level events contain `store_id` and `org_id` whereas, organization-level events contain only `org_id`. ::: ### Example: Typical payload The following example payload [observes](#observable-events) the `order.paid` event. The configured URL receives the following payload. ```javascript { "id": "21a361c9-b117-4d16-be2d-5ed2dbdaa95b", "triggered_by": "order.paid", "attempt": 1, "integration": { "id": "af7bbcc7-f77f-4a8f-abdb-4f039c5c9d81", "integration_type": "webhook", "name": "Order paid notification", "description": "Fire an event on order paid" }, "resources": "{\"data\":{\"type\":\"order\",\"id\":\"1d67160d-dacb-43ed-80ef-c3c4e7ddf764\",\"status\":\"complete\",\"payment\":\"paid\",\"shipping\":\"unfulfilled\",\"customer\":{\"name\":\"Ron Swanson\",\"email\":\"ron.swanson@moltin.com\"},\"shipping_address\":{\"first_name\":\"Jack\",\"last_name\":\"Macdowall\",\"phone_number\":\"123456789\",\"company_name\":\"Macdowalls\",\"line_1\":\"Second Floor, British India House\",\"line_2\":\"15 Carliol Square\",\"city\":\"Newcastle upon Tyne\",\"postcode\":\"NE1 6UF\",\"county\":\"Tyne and Wear\",\"country\":\"GB\",\"instructions\":\"Leave in porch\"},\"billing_address\":{\"first_name\":\"Jack\",\"last_name\":\"Macdowall\",\"company_name\":\"Macdowalls\",\"line_1\":\"Second Floor, British India House\",\"line_2\":\"15 Carliol Square\",\"city\":\"Newcastle upon Tyne\",\"postcode\":\"NE1 6UF\",\"county\":\"Tyne and Wear\",\"country\":\"GB\"},\"links\":{},\"meta\":{\"display_price\":{\"with_tax\":{\"amount\":10000,\"currency\":\"GBP\",\"formatted\":\"£100.00\"},\"without_tax\":{\"amount\":10000,\"currency\":\"GBP\",\"formatted\":\"£100.00\"},\"tax\":{\"amount\":0,\"currency\":\"GBP\",\"formatted\":\"£0.00\"}},\"timestamps\":{\"created_at\":\"2019-07-04T11:12:23Z\",\"updated_at\":\"2019-07-04T11:12:23Z\"}},\"relationships\":{\"items\":{\"data\":[{\"type\":\"item\",\"id\":\"395763ee-1878-4aa0-a7a2-8d4877310d6b\"}]}}},\"included\":{\"items\":[{\"type\":\"order_item\",\"id\":\"395763ee-1878-4aa0-a7a2-8d4877310d6b\",\"quantity\":1,\"product_id\":\"4f28f222-aa5b-442c-9ce9-c223dc7cf15a\",\"name\":\"Spam Fritters\",\"sku\":\"spam-fritters-0716\",\"unit_price\":{\"amount\":10000,\"currency\":\"GBP\",\"includes_tax\":false},\"value\":{\"amount\":10000,\"currency\":\"GBP\",\"includes_tax\":false},\"links\":{},\"meta\":{\"display_price\":{\"with_tax\":{\"unit\":{\"amount\":10000,\"currency\":\"GBP\",\"formatted\":\"£100.00\"},\"value\":{\"amount\":10000,\"currency\":\"GBP\",\"formatted\":\"£100.00\"}},\"without_tax\":{\"unit\":{\"amount\":10000,\"currency\":\"GBP\",\"formatted\":\"£100.00\"},\"value\":{\"amount\":10000,\"currency\":\"GBP\",\"formatted\":\"£100.00\"}},\"tax\":{\"unit\":{\"amount\":0,\"currency\":\"GBP\",\"formatted\":\"£0.00\"},\"value\":{\"amount\":0,\"currency\":\"GBP\",\"formatted\":\"£0.00\"}}},\"timestamps\":{\"created_at\":\"2019-07-04T11:12:23Z\",\"updated_at\":\"2019-07-04T11:12:23Z\"}},\"relationships\":{\"cart_item\":{\"data\":{\"type\":\"cart_item\",\"id\":\"a498b15a-2cc7-49ea-93b3-22143bb403ac\"}}}}]}}", "payload": { "data": { "type": "order", "id": "1d67160d-dacb-43ed-80ef-c3c4e7ddf764", "status": "complete", "payment": "paid", "shipping": "unfulfilled", "customer": { "name": "Ron Swanson", "email": "ron.swanson@moltin.com" }, "shipping_address": { "first_name": "Jack", "last_name": "Macdowall", "phone_number": "123456789", "company_name": "Macdowalls", "line_1": "Second Floor, British India House", "line_2": "15 Carliol Square", "city": "Newcastle upon Tyne", "postcode": "NE1 6UF", "county": "Tyne and Wear", "country": "GB", "instructions": "Leave in porch" }, "billing_address": { "first_name": "Jack", "last_name": "Macdowall", "company_name": "Macdowalls", "line_1": "Second Floor, British India House", "line_2": "15 Carliol Square", "city": "Newcastle upon Tyne", "postcode": "NE1 6UF", "county": "Tyne and Wear", "country": "GB" }, "links": {}, "meta": { "display_price": { "with_tax": { "amount": 10000, "currency": "GBP", "formatted": "£100.00" }, "without_tax": { "amount": 10000, "currency": "GBP", "formatted": "£100.00" }, "tax": { "amount": 0, "currency": "GBP", "formatted": "£0.00" } }, "timestamps": { "created_at": "2019-07-04T11:12:23Z", "updated_at": "2019-07-04T11:12:23Z" } }, "relationships": { "items": { "data": [ { "type": "item", "id": "395763ee-1878-4aa0-a7a2-8d4877310d6b" } ] } } }, "included": { "items": [ { "type": "order_item", "id": "395763ee-1878-4aa0-a7a2-8d4877310d6b", "quantity": 1, "product_id": "4f28f222-aa5b-442c-9ce9-c223dc7cf15a", "name": "Spam Fritters", "sku": "spam-fritters-0716", "unit_price": { "amount": 10000, "currency": "GBP", "includes_tax": false }, "value": { "amount": 10000, "currency": "GBP", "includes_tax": false }, "links": {}, "meta": { "display_price": { "with_tax": { "unit": { "amount": 10000, "currency": "GBP", "formatted": "£100.00" }, "value": { "amount": 10000, "currency": "GBP", "formatted": "£100.00" } }, "without_tax": { "unit": { "amount": 10000, "currency": "GBP", "formatted": "£100.00" }, "value": { "amount": 10000, "currency": "GBP", "formatted": "£100.00" } }, "tax": { "unit": { "amount": 0, "currency": "GBP", "formatted": "£0.00" }, "value": { "amount": 0, "currency": "GBP", "formatted": "£0.00" } } }, "timestamps": { "created_at": "2019-07-04T11:12:23Z", "updated_at": "2019-07-04T11:12:23Z" } }, "relationships": { "cart_item": { "data": { "type": "cart_item", "id": "a498b15a-2cc7-49ea-93b3-22143bb403ac" } } } } ] } }, "configuration": { "secret_key": "secret_squirrel", "url": "https://webhook.url" } } ``` ### Example: Deleted resources payload When resources are deleted and you observe an event, you receive a payload which **only** contains the resource type and ID. ```javascript { "id": "c138854a-5311-4543-a368-01e099f5519b", "triggered_by": "product.deleted", "attempt": 1, "integration": { "id": "4596d5e1-26b6-444a-964d-2b6ec46477fd", "integration_type": "webhook", "name": "Product deleted notification", "description": "Let me know when products are deleted from my store." }, "resources": { "id": "a34a378b-2c39-41e4-a240-6b7e65f5bb55", "type": "product" }, "payload": { "type": "product", "id": "a34a378b-2c39-41e4-a240-6b7e65f5bb55" }, "configuration": { "secret_key": "secret_squirrel", "url": "https://webhook.url" } } ``` ### Message Queue Services The payload of messages delivered to your message queue contains information about the fired event. The information takes the form of a standard cloud event. The following table defines the payload attributes and types: | Attribute | Type | Description | | :-------------- | :------------------------------- | :---------------------------------------------------------------------- | | `id` | `string` | A unique ID for this event. | | `integrationid` | `string` | The ID of the integration being fired. | | `type` | `string` | The [observable event](#observable-events) that triggered this event. | | `data` | `object` | The resource affected by this event. | #### Example: Typical payload The following example payload [observes](#observable-events) the `cart.updated` event. The configured queue receives the following message payload: ```javascript { "data": { "description": "", "id": "a-cart-id", "links": { "self": "https://epcc-integration.global.ssl.fastly.net/v2/carts/a-cart-id" }, "meta": { "display_price": { "discount": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "tax": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "with_tax": { "amount": 200, "currency": "USD", "formatted": "$2.00" }, "without_tax": { "amount": 200, "currency": "USD", "formatted": "$2.00" } }, "timestamps": { "created_at": "2021-05-17T11:30:07Z", "expires_at": "2021-05-24T11:31:08Z", "updated_at": "2021-05-17T11:31:08Z" } }, "name": "Cart", "relationships": { "customers": {}, "items": { "data": [ { "id": "4d28bc2b-9db3-4c96-801b-df0ac5b41552", "type": "custom_item" } ] } }, "type": "cart" }, "datacontenttype": "application/json", "id": "9a21fb54-6c3b-432a-bade-82a60da6b59a", "integrationid": "e17db0d8-467b-4bf3-9c26-3dfe8b96e9d7", "source": "https://epcc-integration.global.ssl.fastly.net", "specversion": "1.0", "storeid": "b33e328f-31a8-4d57-b0a3-ebf1039b3756", "type": "cart.updated" } ``` ### Example: Deleted resources payload When resources are deleted, and you observe an event, the resource delivered in the message only contains the resource type and ID. ```javascript { "data": { "id": "a2733958-1273-4385-9a05-f1ca7684f760", "type": "product" }, "datacontenttype": "application/json", "id": "efca76df-9fc1-4434-ba26-82339d9b723c", "integrationid": "e17db0d8-467b-4bf3-9c26-3dfe8b96e9d7", "source": "https://epcc-integration.global.ssl.fastly.net", "specversion": "1.0", "storeid": "b33e328f-31a8-4d57-b0a3-ebf1039b3756", "type": "product.deleted" } ``` ### Observable Events You can pass multiple observable keys to the `observes` field of the [integration object](/docs/api/integrations/create-integration), or you can create individual events. You can use an array when you handle multiple webhooks at the same URL. Entity/Resource Action Observable Key Store/Organization Address Created address.created Store Updated address.updated Store Deleted address.deleted Store Account Created account.created Store Updated account.updated Store Deleted account.deleted Store Account Member Created account-member.created Store Updated account-member.updated Store Deleted account-member.deleted Store Account Membership Created account-membership.created Store Updated account-membership.updated Store Deleted account-membership.deleted Store Carts Updated cart.updated Store Deleted cart.deleted Store Currency Created currency.created Store Updated currency.updated Store Deleted currency.deleted Store Customer Created customer.created Store Updated customer.updated Store Deleted customer.deleted Store Custom API Entries Created customAPIEntryType.created Store Updated customAPIEntryType.updated Store Deleted customAPIEntryType.deleted Store File Created file.created Store Deleted file.deleted Store Integration (events) Created integration.created Store, Organization Updated integration.updated Store, Organization Deleted integration.deleted Store, Organization One-Time Password Token Request Created one-time-password-token-request.created Store Order Events Checkout Created order.created Store Payments Updated order.updated / order.paid. The event order.paid is triggered when the payment status is paid. The event order.updated is triggered when the order is captured, completed, refunded, anonymized, or updated. Store Authorized order.authorized Store Orders Fulfilled order.fulfilled Store Canceled order.cancelled Store Capture Transaction Paid order.paid. The event order.paid is triggered when the order status is completed and captured, and the payment status is paid. Store Captured order.updated. The event order.updated is triggered when the order is captured, completed, refunded, anonymized, or updated. Store Refund Transaction Refunded order.refunded Store Payment Gateway Updated payment-gateway.updated Store Catalog releases Created catalog-release.created Store, Organization Updated catalog-release.updated Store, Organization Deleted catalog-release.deleted Store, Organization Catalog rules Created catalog-rule.created Store Updated catalog-rule.updated Store Deleted catalog-rule.deleted Store Settings Created settings.created Store Updated settings.updated Store Stock Transaction Created stock-transaction.created Store Transaction Created transaction.created Store Updated transaction.updated Store Tax Items Updated cart.updated Store Subscriptions You can integrate Subscriptions with external systems like enterprise resource planning, fulfilment and other systems. For example, when a subscriber updates their address, the Customer Relationship Management system is updated with the change. See Subscriptions. User Authentication Info Created user-authentication-info.created Store Updated user-authentication-info.updated Store Deleted user-authentication-info.deleted Store :::note Store-level events contain `store_id` and `org_id` whereas, organization-level events contain only `org_id`. ::: Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Integrations Setting up and managing integrations. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## List jobs for integration import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the jobs for the given integration UUID. Request --- ## List logs for integration import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the logs for the given integration UUID. Request --- ## List integrations import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns a list of all integrations created by the store. --- ## List logs for the job import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the integration logs for the given integration and job UUID. Request --- ## List logs for all integrations for the store import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns all integration logs for the store. --- ## Update an integration import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Updates the Integration for the given UUID. Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the integration is not updated. Request --- ## Get a Merchant Realm Mapping import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a Merchant Realm Mapping Request --- ## Get the Merchant Realm Mapping for the current store import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; This API is used to obtain an [Authentication Realm](/docs/api/single-sign-on/authentication-realms) if there is none yet for the current store. --- ## Merchant Realm Mappings Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; The Merchant Realm Mapping object is used to locate the [Authentication Realm](/docs/api/single-sign-on/authentication-realms) which administrators use to sign in to a store via single sign-on. When supplied in the mapping, the prefix field is used during authentication to determine the appropriate authentication realm to sign in with. Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## Update a Merchant Realm Mapping import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a Merchant Realm Mapping Request --- ## Gateways ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Get a Gateway import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the specified gateway. Request --- ## Get all Gateways import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves all gateways. --- ## Payment Gateways Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Payments for orders are processed through a payment gateway. Composable Commerce offers integrations for a selection of payment gateway providers, or you can create your own integrations. Payment transactions are processed similarly for all gateways: 1. A payment transaction is created and an attempt to pay is made. 2. The transaction is forwarded to the third-party gateway specified by the customer. 3. The payment is processed by the third-party gateway. Payment transactions are always processed outside of Composable Commerce for security reasons. Typically, you use a token rather than pass the card details directly. If, however, you want to pass the cart details directly to the third-party provider, Composable Commerce enforces the use of the secure HTTPS protocol. If the transaction is successful, a `200 OK` response is returned. Use the response (success or failure) to update the transaction, which automatically updates the order and payment statuses. A payment transaction can also be refunded. You can select which way you want to process refunds: - Mark as Refunded: You can use your payment gateway’s console to process a refund. Process the refund first in the payment gateway and then use the **Mark as Refunded** capability in Composable Commerce to complete the process. - Refund through Composable Commerce: Start a full or partial refund to a supported payment provider directly from Commerce Manager or the API. You still have the ability to mark as refunded for a pre-integrated gateway, such as Stripe. :::info For nonce-based Authorize.net transactions, if a refund is requested before the transaction has settled (typically within 24 hours), the transaction will be voided instead of refunded. This behavior is specific to nonce-based payments. ::: :::caution Configure your store to use [Manual Gateway](/docs/api/payments/update-manual-gateway) to process payments if the order total is zero or the payment is through non-supported payment providers. ::: ### Order Status Workflow The following image shows the workflow of the order status when you checkout a cart. ![Order Workflow](/assets/Order-Workflow.png) ### Summary of the Workflow 1. [Checkout a cart](/docs/api/carts/checkout). When you checkout a cart, an unpaid order is returned. 2. [Paying for an order](/docs/api/carts/payments). You can process the payment for an order through a payment gateway. You can pay for an order either using purchase payment method or authorize payment method. 3. Confirm the order. Order confirmation might be required when you purchase or authorize a transaction. If you use a purchase method, the order is immediately confirmed. If you use authorize method, funds are captured later when an item is dispatched or restocked, and then the order is considered as complete. See [Capture a Transaction](https://elasticpath.dev/docs/commerce-cloud/payments/transactions/capture-a-transaction). 4. [Fulfill, Refund or Cancel the paid order](/docs/api/carts/refund-a-transaction). The order is considered as fulfilled when it is shipped. You can cancel the order after the checkout or if the order is not fulfilled. You can also choose to refund a partial payment or full payment. 5. (Optional) [Cancel a transaction](/docs/api/carts/cancel-a-transaction). You can cancel or void a pending or authorized transaction. The transaction can be canceled or voided when it is in pending and completed statuses. This works only for Stripe and PayPal and does not work for manual gateway. 6. (Optional) [Anonymize an order](/docs/api/carts/anonymize-orders). You can anonymize an order when it is fulfilled, canceled, or fully refunded. ### Split Payments Split payments involve multiple payment sources for a single order, using externally authorized payments. For example, you can pay for an order using a gift card and a credit card. An order with multiple payment transactions can also be in multiple payment states depending on each transaction. Transactions for split payments are processed similarly for all gateways: 1. A partial payment transaction is created and an attempt to pay the partial amount is made. 2. The transaction for the specified amount is forwarded to the payment gateway specified by the customer. 3. The partial payment is processed. 4. Another partial payment transaction is created and an attempt to pay the remaining amount is made. 5. Another transaction for the remaining amount is forwarded to the payment gateway specified by the customer. 6. The payment is processed, paid, and complete. The payment status must show paid after the order is completed. You can refund transactions for split payments. For more information about refund, see Refund a Payment. The following scenarios show how a shopper can use multiple sources for split payment: - Gift card and credit card - Purchase order and credit card - Store credit and credit card - Employee dollars and credit card - Gift card and loyalty card - Loyalty card and wallet The following image shows a workflow of the split payments. ![Split Payments](/assets/split-payment-workflow.png) The following table describes the payment and order statuses that you can see when an order is passed through multiple stages. | Payment Status | Order Status | Inventory Status | Description | |:-----------------|:-------------|:---------------------|:------------| | `partially_authorized` | `incomplete` | Allocated | Indicates that the payment is partially_authorized and the balance_owing value is greater than zero. In this case, one of the transactions is authorized and complete. | | `partially_paid` | `incomplete` |Allocated | Indicates that the funds are captured but the balance_owing value is greater than zero. In this case, one of the transactions is captured or purchase is complete. | | `unpaid` | `incomplete` | Not Allocated | Indicates that the order does not have any complete payment transactions. In this case, all the transactions or any of the transactions can be still pending. | | `authorized` | `processing` | Allocated | Indicates that completed transactions cover the entire total amount for an order and at least one of the transactions is authorized. | | `paid` | `complete` | Allocated | Indicates that the order is complete and the amount for the order is fully paid when all authorized transactions are captured or purchase transactions are complete. | Contact Elastic Path: URL: [https://elasticpath.com](https://elasticpath.com) --- ## Update Adyen Gateway import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to configure Adyen. Request --- ## Update Authorize.net Gateway import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to configure Authorize.net. :::note The credentials used for a test account may differ from those used for a live account. When configuring the payment gateway with your credentials and setting `test` to `true`, the system allows you to test various Authorize.net payment interactions to ensure everything works as expected. Once you are ready to go live, update `test` as `false` to direct requests to the live endpoints instead of the test account. Additionally, ensure that you switch to the credentials for the live account when making this change. To access your sandbox environment, see [Authorize.net Sandbox account](https://developer.authorize.net/hello_world/sandbox.html). ::: Request --- ## Update Braintree Gateway import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to configure Braintree. Request --- ## Update CardConnect Gateway import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to configure CardConnect. Request --- ## Update CyberSource Gateway import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to configure CyberSource. Request --- ## Update Elastic Path Payments Powered by Stripe import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to configure Elastic Path Payments Powered by Stripe in Commerce. :::note You can contact Elastic Path sales or [customer success team](mailto:customersuccess@elasticpath.com) to get more information about Elastic Path Payments Powered by Stripe and to check whether it will work for you. ::: Request --- ## Update Manual Gateway import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; This endpoint allows you update the manual gateway. Request --- ## Update PayPal Express Checkout import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to configure PayPal Express Checkout. :::note To learn more about PayPal Express Checkout and check whether it will work for you, contact your sales or [customer success team](mailto:customersuccess@elasticpath.com). ::: Request --- ## Update Stripe Gateway import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to configure Stripe. Request --- ## Update Stripe Payment Intents Gateway import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to configure Stripe Payment Intents. Request --- ## Create A Custom API Role Policy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create A Custom API Role Policy Request --- ## Custom API Role Policies A Custom API Role Policy defines the level of access a role has to a Custom API. By default, administrative roles like **Store Admin** or **Org Admin** have full access to all Custom APIs. To grant access to other roles, a policy must be created for that specific role and Custom API. Below are the permissions that can be assigned to a role: | Permission | Description | |------------|------------------------------------------| | **Create** | Create a Custom API Entry. | | **List** | Retrieve a list of Custom API Entries. | | **Read** | Get a Custom API Entry. | | **Update** | Update a Custom API Entry. | | **Delete** | Delete a Custom API Entry. | ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Delete a Custom API Role Policy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete A Custom API Role Policy Request --- ## Get a Custom API Role Policy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get A Custom API Role Policy Request --- ## Get a Standard Shopper Role import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a Standard Shopper Role Request --- ## Get a Standard User Role import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a Standard User Role Request --- ## List Custom API Role Policies import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of Custom API Role Policies ## Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) Custom API Role Policies: | Attribute | Operators | Example | |------------------|-------------------------------|----------------------------------------------------------| | `id` | `lt`,`le`,`eq`,`gt`,`ge`,`in` | `eq(id,3fa85f64-5717-4562-b3fc-2c963f66afa6)` | | `created_at` | `lt`,`le`,`eq`,`gt`,`ge` | `ge(created_at,2024-04-29T00:00:00.000Z)` | | `updated_at` | `lt`,`le`,`eq`,`gt`,`ge` | `le(updated_at,2024-04-29T00:00:00.000Z)` | | `custom_api_id` | `eq` | `eq(custom_api_id,fded1d2a-8bb8-48b6-86a5-9eb05cc8626a)` | | `role_id` | `eq` | `eq(role_id,it-developer)` | ## Sorting The following attributes are available for sorting. When specified, the results are sorted in ascending order based on the value of the field. To sort in descending order, prefix the attribute with `-`, for example, `-updated_at`. The default sort order is `created_at` in descending order. - `id` - `created_at` - `updated_at` Request --- ## List Standard Shopper Roles import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of Standard Shopper Roles --- ## List Standard User Roles import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of Standard User Roles --- ## Permissions Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; A user's permissions are determined by their assigned role, which defines their level of access to APIs and Commerce Manager. These permissions ensure that users can only perform actions and access data relevant to their responsibilities. With [Commerce Extensions](/docs/api/commerce-extensions/commerce-extensions-introduction), you can create Custom APIs to extend the functionality of Commerce. Using Custom API Role Policies, you can specify the permissions for each role, ensuring fine-grained control over who can interact with these Custom APIs. Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## Standard Shopper Roles Standard Shopper Roles represent the roles of customers. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Standard User Roles Standard User Roles represent the roles that can be assigned to users through Commerce Manager. These roles define the level of access a user has to Commerce Manager. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Update a Custom API Role Policy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update A Custom API Role Policy Request --- ## Get Personal Data Erasure Request import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; This request serves to get an existing erasure request by its ID. Request --- ## Get all Personal Data Erasure Request import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Gets a list of erasure requests for a specific resource id and resource type. You can use pagination with this resource. For more information, see [pagination](/guides/Getting-Started/pagination). ## Filtering The following operator and attributes are **required** for [filtering](/guides/Getting-Started/filtering) erasure requests. | Operator | Description | |:---------|:-----------------------------------------------------------------------------------------------------| | `eq` | Checks whether the values of two operands are equal. If the values are equal, the condition is true. | | Attribute | Type | Operator | Example | |:----------------| :--- | :--- |:--------------------------------------------------------| | `resource_type` | `string` | `eq` | `eq(resource_type,customer)` | | `resource_id` | `string` | `eq` | `eq(resource_id,0f850c15-d643-480a-a2b4-9e3c26067178\)` | Request --- ## Get Logs Time-to-Live (TTL) Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get Logs Time-to-Live (TTL) Settings --- ## Get Personal Data Logs import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Gets a list of logs for a specific resource id and resource type. You can use pagination with this resource. For more information, see [pagination](/guides/Getting-Started/pagination). :::note * This request is only accessible to `client_credentials` token users with `Seller Admin`, `Support` and `IT` roles. * Non `client_credentials` token users cannot access this endpoint. See [Permissions](/docs/authentication/tokens/permissions). * This request requires a filter for `resource_type` and `resource_id`. ::: ## Filtering The following operator and attributes are **required** for [filtering](/guides/Getting-Started/filtering) erasure requests. | Operator | Description | |:---------|:-----------------------------------------------------------------------------------------------------| | `eq` | Checks whether the values of two operands are equal. If the values are equal, the condition is true. | | Attribute | Type | Operator | Example | | :---------------- | :--- | :--- | :-------------------------------------------------------- | | `resource_type` | `string` | `eq` | `eq(resource_type,customer)` | | `resource_id` | `string` | `eq` | `eq(resource_id,0f850c15-d643-480a-a2b4-9e3c26067178)` | Request --- ## Get Personal Data Related Data Entries import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Gets a list of related data entries filtered by specific resource id and resource type. You can use pagination with this resource. For more information, see [pagination](/guides/Getting-Started/pagination). :::note * This request is only accessible to `client_credentials` token users with `Seller Admin`, `Support` and `IT` roles. * Non `client_credentials` token users cannot access this endpoint. See [Permissions](/docs/authentication/tokens/permissions). * This request requires a filter for `resource_type` and `resource_id`. ::: ## Filtering The following operator and attributes are **required** for [filtering](/guides/Getting-Started/filtering) erasure requests. | Operator | Description | |:---------|:-----------------------------------------------------------------------------------------------------| | `eq` | Checks whether the values of two operands are equal. If the values are equal, the condition is true. | | Attribute | Type | Operator | Example | | :---------------- | :--- | :--- | :-------------------------------------------------------- | | `resource_type` | `string` | `eq` | `eq(resource_type,customer)` | | `resource_id` | `string` | `eq` | `eq(resource_id,0f850c15-d643-480a-a2b4-9e3c26067178)` | Request --- ## Logs Time to Live Settings You can use the Logs TTL Settings endpoint to retrieve and update settings controlling logs time-to-live (TTL). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Personal Data Erasure Requests Erasure requests enable you to exercise the right, referred to in regulations such as GDPR, as the right to be forgotten or right to erase. Erasure requests allow you to wipe out personal data from Commerce in an automated way, including: * All related resources (for example, addresses, customers, and so on.) * Personal Data Logs Erasure requests can be created for any data entry in the personal data set (see [Personal Data Concept](/docs/api/personal-data/personal-data-introduction) for details), and the result is the same. :::note Currently, it does not include flows or data external to Commerce. ::: Erasure requests are processed asynchronously. The POST requests return immediately, and processing continues in the background. You can use the GET endpoint to poll for results until you see `{..."status":"SUCCESS"...}` in the response body. In the unlikely event an erasure request fails (if the status is not equal to `SUCCESS`), you are advised to retry by creating another erasure request. If the problem persists, contact Support. :::note Currently, personal data management is only enabled for a limited set of endpoints. See the [personal data concepts page](/docs/api/personal-data/personal-data-introduction) for the list of endpoints that support personal data management. ::: Seller Admin & IT users have full access to Erasure Requests, and Support users have read access. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Personal Data Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; In Commerce, every change to a user’s personal data is logged. Personal data sets are groups of data items that are related to each other. For example, customer, addresses, and authentication information. The contents of a personal data set is dynamic. Data items are attached to each other automatically as they are created or updated. The API allows you to fetch these logs, including the list of related data items. In other words, the data items that belong to the same personal data set. Log entries are kept in the system for a limited time. You can configure the retention period using the Logs Time-to-live (TTL) settings API. The default retention period is 365 days for production store types and 7 days for other store types. ## Personal Data Resource Types | Entity type | Endpoint | Documentation | |-------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------| | customer | `v2/customers/{id}` | [Customers](/docs/customer-management/customer-management-api/customer-management-api-overview) | | account | `v2/accounts/{id}` | [Accounts](/docs/api/accounts/post-v-2-accounts) | | account-member | `v2/account-members/{id}` | [Account Members](/docs/api/accounts/account-members) | | account-membership | `v2/accounts/{accountId}/account-memberships/{id}` | [Account Memberships](/docs/api/accounts/account-membership) | | address | `v2/customers/{customerId}/addresses/{id}`; `v2/accounts/{accountId}/addresses/{id}` | [Addresses](/docs/api/addresses/addresses-introduction) | | user-authentication-info | `v2/authentication-realms/{realmId}/user-authentication-info/{id}` | [User Authentication Info](/docs/api/single-sign-on/user-authentication-infos) | | user-authentication-oidc-profile-info | `v2/authentication-realms/{authenticationRealmId}/user-authentication-info/{userAuthenticationInfoId}/user-authentication-oidc-profile-info/{id}` | [User Authentication OIDC Profile Info](/docs/api/single-sign-on/user-authentication-oidc-profile-infos) | | user-authentication-password-profile-info | `v2/authentication-realms/{authenticationRealmId}/user-authentication-info/{userAuthenticationInfoId}/user-authentication-password-profile-info/{id}` | [User Authentication Password Profile Info](/docs/api/single-sign-on/user-authentication-password-profile-infos) | | order | `v2/orders/{id}` | [Orders](/docs/api/carts/orders) | Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## Personal Data Logs When a user’s personal data is changed, an event is logged by Commerce. You can use the Personal Data Logs endpoint to access these logs. This API is read only, and you cannot add, update, or delete logs using this API. The API only allows you to read all logs for a particular data entry (specified in the filter GET parameter). :::note Currently, personal data management is only enabled for a limited set of endpoints. See the [personal data concepts page](/docs/api/personal-data/personal-data-introduction) for the list of endpoints that support personal data management. ::: ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Personal Data Related Data Entries This is a supplementary endpoint for the [logs](/docs/api/personal-data/logs-time-to-live-settings) endpoint. It allows you to view all data entries that are related to the resource specified in the filter. For example, a user can get all data items that relate to a customer, such as addresses or user authentication info. This API is read only, and you cannot add, update, or delete anything using this API. The API only allows you to list related data items for a particular data entry (specified in the filter GET parameter). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Create Personal Data Erasure Request import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; This request serves to create a new erasure request for a given resource ID and Type. All resources that belong to the same personal data set will be erased. Request --- ## Update Logs Time-to-Live (TTL) Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update Logs Time-to-Live (TTL) Settings Request --- ## Cancel a Job import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Cancels an asynchronous job whose status is pending or processing. Request --- ## Create a Promotion Job import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to create an asynchronous job to generate codes and export promotion codes. Request --- ## Create a Promotion import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can use this endpoint to create the following types of promotion: - Cart Fixed Discount Promotion - Cart Percent Discount Promotion - X for Y Discount Promotion - X for Amount Discount Promotion - Fixed Bundle Discount Promotion - Item Fixed Discount Promotion - Item Percent Discount Promotion - Free Gift Promotion ### The `schema` object Promotions are defined by schemas that are used internally to verify promotions and calculate discounts. You must define a schema when you create the promotion. For more information, see the schema.exclude criteria and the targeting fields criteria. #### The `schema.exclude` criteria When creating a promotion, you can specify when it **should not** be applied. The promotion will not be applied on any cart (or cart item, depending on the promotion type) that fulfills at least one of the `schema.exclude` criteria. The following criteria can be set to exclude items from a promotion: - `schema.exclude.targets` - `schema.exclude.nodes` - `schema.exclude.attributes` - `schema.exclude.conditions` For example, if you want to create a promotion with value as *SKU1* in `schema.exclude.targets` and and color *yellow* and size *small* in `schema.exclude.attributes`, then any products with *SKU1* or the color *yellow* or the size *small* will be excluded from the promotion. To exclude products from a promotion based on multiple conditions at the same time, use `schema.exclude.conditions`. For example, use `schema.exclude.conditions` to exclude items that are both *yellow* in color and *small* in size. #### The targeting fields criteria When creating a promotion, you can also specify when it **should** be applied. To define the targeted products, use the following fields: - `schema.target_catalogs` - `schema.targets` - `schema.target_nodes` - `schema.target_attributes` - `schema.target_conditions` The cart item's catalog is verified if you define the `schema.target_catalogs` field. If the item is in any of the targeted catalogs specified in `schema.target_catalogs`, the promotion will be applied. If the item is not in any of the catalogs, the promotion will not be applied. Then, the cart item is verified to see if it fulfills at least one criteria of any of the four other targeting fields. In other words, the `schema` targeting fields such as `schema.targets`, `schema.target_nodes`, `schema.target_attributes` and `schema.target_conditions` create *OR* targeting conditions. For example, if you create a promotion with values as *SKU1* in `schema.targets` and color *yellow* and size *small* in `schema.target_attributes`, then it will be applied to any products with *SKU1* or the color *yellow* or the size *small*. To create a promotion that targets products based on multiple conditions at the same time, use `schema.target_conditions`. For example, use it to target items that are both *yellow* in color and *small* in size. :::note For Cart Fixed Discount Promotion and Cart Percent Discount Promotion, the cart item's catalog is verified if you define the `schema.target_catalogs` field. If the item is in any of the targeted catalogs specified in `schema.target_catalogs`, the promotion will be applied. If the item is not in any of the catalogs, the promotion will not be applied. ::: :::caution - Line-item discounts are only supported by the line calculation method. For more information about this method, see the Calculation Method section. - Hierarchy-based promotions are not supported for fixed bundle discount promotion and free gift promotion. To promote a bundle, create the bundle in Product Experience Manager, and then create a promotion for that bundle. For more information, see Bundles in Product Experience Manager. - For Free Gift Promotion, we recommend using `auto_add_free_gift` feature with `automatic` setting enabled. When `automatic` is set to `true`, it indicates that promotions are added automatically, and discounts are applied accordingly. If you enable the `auto_add_free_gift`, but do not enable the `automatic` setting, gift items will be added without discounts. In this case, shoppers need to apply coupon codes twice, first to add the gift item and then to apply the discount. ::: Request --- ## Create Promotion Codes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to create promotion codes for a specific promotion. :::note When a promotion expires, the promotion codes attached to the promotion automatically become invalid. However, when you re-enable the expired promotion, the promotion codes attached to the promotion are deleted. ::: Request --- ## Delete a Promotion Code import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to delete a single promotion code. Request --- ## Delete a Promotion import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to delete a specific promotion. Request --- ## Delete Multiple Promotion Codes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to delete multiple promotion codes within a specific promotion. Request --- ## Get a Promotion History import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to retrieve a promotion history. Request --- ## Get a Promotion import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a promotion. Request --- ## Get all Promotions import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns all promotions. :::note You can use pagination with this resource. For more information, see [pagination](/guides/Getting-Started/pagination). ::: ### Filtering The following operators and attributes are available when filtering on this endpoint. See [Supported Filtering Characters](https://elasticpath.dev/guides/Getting-Started/filtering#supported-characters). Use `code` filter to search codes within promotions. | Attribute | Type | Operator | Example | |:-----|:---------|:---------|:----------------------------------------| | `code` | `string` | `eq` | `eq(code,some_code)` | For filtering advanced promotion usages, pass the `EP-Public-Search-Type=cm_search` header. Advanced search filtering is only applicable when the promotion code is consumed and the promotion is not deleted. | Attribute | Type | Operator | Example | |:-----|:---------|:---------|:----------------------------------------| | `promo_id` | `string` | `eq` | `eq(promo_id, 69c63c9d-8ccf-44b1-8e98-1e7feebfb581)` | | `promo_name` |`string` | `eq`, `like` | `eq(promo_name,cart percent discount)` | | `promo_type` | `string` | `eq` | `eq(promo_type,fixed_discount)` | | `promo_status` | `string` | `eq` | `eq(promo_status,Running)` | | `promo_checkouts` | `string` | `eq`,`gt`, `ge`, `lt`, `le` | `eq(promo_checkouts,2)` | | `promo_skus_prod_ids` | `string` | `eq`, `like` | `eq(promo_skus_prod_ids, sku1)` | | `promo_start_date` | `string` | `eq`, `gt`, `gr`, `lt`, `le` | `eq(promo_start_date,2023-01-01)` | | `promo_end_date` | `string` | `eq`, `gt`, `gr`, `lt`, `le` | `eq(promo_end_date,2050-06-15)` | | `code_id` | `string` | `eq` | `eq(promo_id,2ea0cd1d-43a9-441b-b03f-3cab84aaee0c):eq(code_id,14b55e6c-3f80-436e-a90a-4de5f0e36240)` | | `code_code` | `string` | `eq`, `like` | `eq(code_code,cart_fixed_10)` | | `code_used` | `string` | `eq`, `gt`, `gr`, `lt`, `le` | `eq(code_used,2)` | | `code_created_date` | `string` | `eq`, `gt`, `gr`, `lt`, `le` | `eq(code_created_date,2023-11-15)` | | `order_id` | `string` | `eq`, `like` | `eq(order_id,ccb13673-627c-4976-88da-f77c542b528f)` | | `order_customer_email` | `string` | `eq`, `like` | `like(order_customer_email,andy*)` | | `order_created_date` | `string` | `eq`, `gt`, `gr`,`lt`, `le` | `le(order_created_date,2023-11-15)` | Request --- ## Get Promotion Code Exported File import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves exported codes in a CSV format. Request --- ## Get Promotion Codes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can use this endpoint to retrieve promotion codes. :::note - The `codes.max_uses` attribute represents the maximum usage of the codes. - The `codes.uses` attribute represents the remaining number of times the codes can be used for the promotion. - Codes created before April 27, 2023 will only have `codes.uses` attribute in the response body. ::: Request --- ## Get Promotion Jobs import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the list of jobs for a specific promotion. In the response example, you can see the `result.generated` field, which indicates the number of codes generated during the job processing. Additionally, you may also see the optional `result.deleted` field, indicating the number of codes deleted during the job cancellation. The parameters and result objects are shown only when `job_type` is `code_generate`. ### Filtering The following operators and attributes are available when filtering on this endpoint. | Attribute | Type | Operator | Example | | ----------| ----- | -------- | ------ | | `job_type` | `string` | `eq` | `eq(job_type, code_export)` | | `status` | `string` | `eq` | `eq(status, complete)` | ### Errors If an error occurs during job processing, the response includes an optional error field. For example, when you `GET` promotion jobs, the following response shows the details within the error field if an error occurred during job processing. ```json \{ "data": [ \{ "type": "promotion_job", "id": "84d86114-a92d-4c34-92f1-3e36ef6cabeb", "promotion_id": "ad386702-e780-42c6-b190-0527ad768917", "job_type": "code_generate", "name": "job", "parameters": \{ "number_of_codes": 1000, "consume_unit": "per_cart", "max_uses_per_code": 1, "code_length": 8, "code_prefix": "promo-" \}, "status": "failed", "error": "codes limit exceeded", "meta": \{ "timestamps": \{ "created_at": "2023-12-06T13:52:29.587Z", "updated_at": "2023-12-06T13:54:49.133Z" \} \} \} ], "links": \{ "current": "https://useast.api.elasticpath.com/v2/promotions/ad386702-e780-42c6-b190-0527ad768917/jobs?page[offset]=0&page[limit]=25", "first": "https://useast.api.elasticpath.com/v2/promotions/ad386702-e780-42c6-b190-0527ad768917/jobs?page[offset]=0&page[limit]=25", "last": "https://useast.api.elasticpath.com/v2/promotions/ad386702-e780-42c6-b190-0527ad768917/jobs?page[offset]=0&page[limit]=25", "prev": "https://useast.api.elasticpath.com/v2/promotions/ad386702-e780-42c6-b190-0527ad768917/jobs?page[offset]=0&page[limit]=25", "next": "https://useast.api.elasticpath.com/v2/promotions/ad386702-e780-42c6-b190-0527ad768917/jobs?page[offset]=0&page[limit]=25" \}, "meta": \{ "page": \{ "limit": 25, "offset": 0, "current": 1, "total": 1 \}, "results": \{ "total": 1 \} \} \} ``` Request --- ## Promotion Codes You can apply promotions automatically to all customer carts, or you can create promotion codes that customers must enter to receive the discount. You can enable this feature by setting the automatic attribute to `false` in the promotions schema when you create a promotion. For more information, see [Create Promotion Codes](/docs/api/promotions/create-promotion-codes). You can generate and export codes for a promotion using the bulk code generation feature, which allows you to create a large number of unique codes and export them in CSV format. For details, refer to the [Generating Bulk Codes](/docs/commerce-manager/promotions-standard/overview#generating-bulk-codes) and [Managing Export Codes](/docs/commerce-manager/promotions-standard/overview#managing-code-export) sections. You can generate a maximum of 1000 codes for a promotion. If you need to generate more than 1000 codes, limit the promotion's duration to a maximum of 365 days from its start date. The promotion expiry date is 365 days. With the consume unit feature, you can limit the number of usages of a code for a promotion. You must create a code for this promotion to track the usage of the promotion. The consume unit options are `per_cart` and `per_item`. For example, consider a store that offers 50% off on *SKU1*, but limits the promotion to a maximum of two usages. Under the `per_cart` setting, a shopper can buy *SKU1* twice in a separate transaction, each at a 50% discount. However, with the `per_item` setting, if a shopper buys two SKU1s in a single purchase, both items count toward the promotion's usage limit. Therefore, the shopper would use up both usages of the promotion in a single purchase. Promotion codes can be group codes or individual codes. For example, you can offer a seasonal discount to all customers, such as *SUMMER-SALE*, or you can offer preferred customers unique discount codes. Promotion codes expire automatically at the end of the promotion period and are removed from the promotion. When a promotion expires, the promotion codes attached to the promotion automatically become invalid. However, when you re-enable the expired promotion, the promotion codes attached to the promotion are deleted. When you checkout a cart with an expired promotion, the expired promotion will be automatically removed from a cart and the checkout process is initiated. As a best practice, we recommend to update your cart to remove the expired promotion before initiating the checkout process. When extending the end date of an expired promotion with over 1000 codes, you will receive an error response. See [Update a Promotion](/docs/api/promotions/update-a-promotion). In such cases, we recommend [duplicating the promotion](/docs/commerce-manager/promotions-standard/overview#duplicating-promotions), allowing you to set the new end dates and create promotion codes as needed. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Promotion Jobs Use Jobs API to initiate a job within a promotion. Jobs operate asynchronously and have a different status based on their progress. The following are the job statuses: - `pending`: Commerce has received the request but is currently busy processing other requests. - `processing`: Commerce has initiated processing the job. - `completed`: The job is successfully completed. - `failed`: The job has failed. - `cancelling`: The job is currently in the process of being canceled. You need to wait for the cancellation process to complete. This occurs prior to the `cancelled` status. For example, if you cancel a big `code_generate` job, it may take some time for the cancellation to complete since part of the cancellation process involves deleting the generated codes. - `cancelled` : The job request is canceled. ![Promotion Job Statuses Workflow](/assets/job_status_workflow.png) ### Characteristics of Jobs - You can only initiate one job at a time within a promotion. If you want to run another job for the same promotion, you must wait until the previous job is `completed` or `failed`. However, you can create new jobs for different promotions even if there are `pending` jobs in other promotions. - If you intend to manage promotions with more than 10,000 codes per promotion, we recommend [exporting codes](/docs/api/promotions/create-a-promotion-job) for viewing purposes instead of attempting to view them within Commerce Manager. This recommendation is made due to our enforced maximum page offset limit of 10,000. Altering the page_offset_limit value poses potential performance risks to the platform. - A `code_generate` job is initiated even if the maximum allowable number of codes for the promotion has been reached. However, when processed, this job will fail. To view the status of this failed job, you can only do so by passing [GET Jobs](/docs/api/promotions/get-promotion-jobs) request. - A limited number of jobs can be processed at a time. Jobs are queued and processed sequentially, one after the other. You can expect a certain delay before job processing. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Promotions Standard Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Promotions Standard offer the flexibility to provide different types of discounts to all your customers or specific customers. You can apply promotions automatically to all purchases, or alternatively, create promotion codes that customers must enter to receive a discount. You can have multiple promotions active at the same time. Promotions are active in a fixed duration, with defined start and end dates. However, you can manually stop a promotion at any time. For testing your promotions when scheduling a future date for your shopping cart, you can use the [Preview Cart API](/docs/api/carts/create-a-cart#preview-cart). When [Creating a Free Gift Promotion](/docs/api/promotions/create-a-promotion), set the promotion to automatic and enable the `auto_add_free_gift` feature. This way, the shopper will see the free gift in their shopping cart when the target product is added to the cart, and the discount will be applied. This eliminates the need for an additional step to apply the code for the gift discount. However, if you desire more control over when or how the free gift is added, you can choose to use a promotion code and disable the **Automatically add free gift items to the cart** toggle in Commerce Manager. See [Creating Free Gift Promotions](/docs/commerce-manager/promotions-standard/item-level-promotions/free-gift-promotions). For a seamless process, ensure that the currencies of automatically added gift items match with those of the items that initiate free gifts. Additionally, ensure that the free gift item is within the same catalog as the eligible items. For inventory-managed products, ensure that you have sufficient inventory available to run the promotion. If there is insufficient stock of free gift items for all eligible free products, the free gifts won't be added to the cart. Promotions Standard can be: - [Cart-level promotions](#cart-level-promotions): The promotion applies to the entire cart. - [Item-level promotions](#item-level-promotions): The promotion applies to individual items in a cart. :::note The shipping prices do not impact eligibility for item-level and cart-level promotions. ::: All items in the cart are eligible for cart-level promotions, even if they already have item-level promotions applied. You can select a few products and exclude them from a cart-level promotion. However, the store that uses a simple calculation method does not support promotions with the exclude setting. ### Cart-level Promotions Cart-level promotions are applied to all items in the cart. Cart-level promotions include: - Fixed discount: Reduces the cart total by a fixed amount, such as $5.00 off. - Percentage discount: Reduces the cart total e by a specific percentage, such as 10% off. The following image shows a cart before and after applying a 10% Off promotion. With the discount applied, the price for each item is reduced by 10% and the cart total reflects the reduction. ![Each item in the cart shows a price that is 10% less than the catalog price.](/assets/promotions-cart-10-percent-off.png) All items in the cart are eligible for cart-level promotions, even if they already have item-level promotions applied. You can select a few products and exclude them from a cart-level promotion. However, the store that uses a [simple calculation method](https://elasticpath.dev/guides/How-To/Carts/calculate-totals#simple-calculation-method) does not support promotions with the `exclude` setting. ### Item-level Promotions Item-level promotions are applied to each item that qualifies for the promotion. In a shopping cart, the price of each item reflects the discount applied to each item. With the `max_applications_per_cart` setting, you can limit the number of purchases of an item at the sale price in a cart. For more information, see the Promotions API section. Item-level promotions include the following promotion types: - X for Y: Offers bulk discount based on unit price, such as 2-for-1 sales. - X for amount: Offers a bulk discount based on a fixed price, such as 3-for-$20 sales. - Bundle: Offers bulk discount when selected products are purchased together. For example, Buy any two items from the list for $100. - Item fixed discount: Reduces the price of multiple items by a fixed amount, such as $5.00 off. - Percentage item discount: Reduces the product price for multiple items by a specific percentage, such as 10% off. You can also count the number of usages of the promotion per SKU item and limit the usage of the promotion per item. For example, if the usage of the promotion is limited to ten and the shopper purchases two of the same item and three of the another item, five uses of the promotion is deducted from the total usage limit. - Free Gift: Offers a free item when a specific product or a group of products are purchased. :::caution - Item-level promotions are only supported by the line calculation method. For more information about this method, see the [Calculation Method](/docs/api/settings/settings-introduction#calculation-method) section. - The `max_discount_value` setting specifies the maximum possible discount for the cart. To avoid the conflict with the promotions and the promotion to work, we recommend not to use this setting for the following promotions: - Cart-level fixed discount - Item fixed discount - X for Y discount - X for amount discount - Bundle - Free gift - The `max_applications_per_cart` setting, which specifies the maximum number of applications of a promotion per cart, is applicable to line-item promotions only. For example, in a store that offers *buy SKU1 get a free gift* promotion with maximum application per cart set to one, the buyer can only use the free gift promotion once per cart. If maximum application per cart is not set, the buyer can use the promotion multiple times. You can also set maximum application per cart to zero to remove any usage limit. - The `exclude` array consists of productIDs or SKUs of products to be excluded from the cart-level promotions, such as `fixed_discount` and `percent_discount`. However, the stores that use simple calculation method do not support excluding products from promotions. - Already existing promotions created before September 28, 2022 will not have `created_by` and `updated_by` attributes in their response body. ::: You can create codes for a promotion so that customers receive the discount only when the code is provided. ### Multiple promotions for the same SKU You can have multiple promotions for the same SKU. However, each instance of the SKU in the cart is eligible for only one item-level promotion. :::note The promotions are applied in the order of date of creation of the promotions. The oldest promotion is applied first and the newest promotion is applied last. For each instance of a SKU that matches the criteria in the oldest promotion, the promotion is applied. For the remaining instances of the SKU, each instance is compared to the criteria for the next oldest promotion. ::: For example, a cart consists of 1 *BestEver Coffee Maker* and 2 *BestEver Coffee Grinders*. The following promotions are available and applied automatically without a code: - An existing *BestEver Coffee Maker* + *Grinder* bundle promotion for $200.00. The bundle discount is distributed among the items in the bundle depending on the price of each item. - A newly added *BestEver Coffee Grinders* 10% Off percentage item discount promotion. In this example, *BestEver Coffee Maker* costs $150 and *BestEver Coffee Grinder* costs $100. The promotions work in the following order: 1. The $50 bundle discount is distributed among the items depending on the cost. In this example, the cost proportion of products is 3:2 and the *BestEver Coffee Maker* gets $30 discount and *BestEver Coffee Grinder* gets $20 discount. 2. The second promotion is applied to the remaining *BestEver Coffee Grinders* item, and the price is reduced to $90. 3. The cart total after both discounts is $290 instead of $350. ### Understanding how Promotions work with Bundles #### Discounting Promotion Bundles Bundles offer a bulk discount when selected products are purchased together. For example, for a bundle promotion, (SKU1 or SKU2 ) + SKU3, the promotion is applied if the bundle includes either SKU1 and SKU3 or SKU2 and SKU3. This setup encourages the purchase of multiple items together at a discounted rate. #### Discounting Product Bundles via promotions For both Cart-level promotions and Item-level promotions, discounts are applied at the bundle level that can have fixed bundle price or automatic/cumulative pricing. It is important to note that promotions do not apply to components within a bundle even if the individual item within the components qualifies for promotion. See the following examples: - **Example 1**: Consider that Playtend Games offers a bundle that includes a game console, the Playtend Invaders Game, and the Invaders Controller. If there is an existing Item Percent Discount for the Playtend Invaders Game when sold separately, this discount will not apply when the game is part of the bundle. This ensures that the bundle pricing strategy is maintained. - **Example 2**: In the case of Attribute-based promotions, consider a bundle that consists of *Item A* with attribute *Brand A* and *Item B* with attribute *Brand B*. If *Item A* with attribute *Brand A* qualifies for Item Percent Discount promotion, this discount is not applied to the bundle since the *Item A* is a component item within the bundle. To learn how to create a bundle, see [Create a Bundle](/docs/api/pxm/products/create-product). ### Condensed Promotion A condensed promotion is essentially an object that contains specific meta information about a promotion applied to the cart or order. Condensed promotions can be retrieved from the following endpoints: - [Get a Cart](/docs/carts-orders/Includes#get-retrieve-promotions-from-a-cart): This endpoint displays cart-level condensed promotions within the included object. If `?include=items` is specified, the included object also contains cart item-level promotions. The relationships field at the cart level has a promotions section only when `?include=promotions` is specified. - [Get Cart Items](/docs/carts-orders/Includes#get-retrieve-promotions-from-cart-items): This endpoint shows both cart-level and item-level discounts in a condensed format within the included object. - [Get an Order](/docs/carts-orders/Includes#get-retrieve-promotions-from-an-order): This endpoint displays order-level condensed promotions within the included object. - [Get Order items](/docs/carts-orders/Includes#get-retrieve-promotions-from-order-items): This endpoint displays both order-level and item-level promotions in the included object. This applies to both Promotions Standard and [Rule Promotions](/docs/promotions-builder/overview). Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: URL: [https://elasticpath.com](https://elasticpath.com) License MIT --- ## Promotions Standard ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Update a Promotion import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to update a specific promotion. :::note You can re-enable an expired promotion by updating the end date to a future date. However, when you enable a promotion again, all codes previously attached to it are deleted to make sure that duplicate promotion codes do not exist on different promotions. ::: ### Errors When extending the end date of an expired promotion with over 1000 codes, you will receive the following error response. In such cases, we recommend duplicating the promotion, allowing you to set the new end dates and create promotion codes as needed. ```json { "errors": [ { "status": 422, "source": "request", "title": "Unprocessable Entity", "detail": "" } ] } ``` Request --- ## Anonymize Rule Promotion Usages import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Anonymizes user-related data in Rule Promotion usage records. This operation is typically used for GDPR compliance or privacy-related requests. - This process replaces identifiable user data with anonymized placeholders. - Affects all recorded promotion usages where customer data is stored. - Does not impact historical transaction records or applied discounts. A successful request returns a `200 OK` response with the anonymized usage records. Request --- ## Cancel a Rule Promotion Job import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Cancels an asynchronous job for a rule promotion if its status is `pending` or `processing`. - Only jobs that have not yet completed can be canceled. - Once canceled, no further processing occurs, and partially completed results may be deleted. Request --- ## Create Rule Promotion Codes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Creates new promotion codes for a specific rule promotion, allowing customers to redeem discounts based on predefined conditions. - Supports bulk creation of multiple promotion codes in a single request. - Each code can have individual usage limits. - Can optionally assign codes to specific users to enforce targeted promotions. - The promotion codes are case-insensitive. :::note Regarding first time shopper limitations: - Orders without payment transactions do not count as completed purchases. - Canceling or refunding an order does not reinstate first-time shopper status. - A first-time shopper coupon code cannot have limited uses or be assigned to specific users, meaning the code cannot be restricted by the number of times it can be used or tied to a specific customer ID. ::: A successful request returns a `201 Created` response with details of the generated promotion codes. ### Duplicate Codes Duplicate promotion codes **are supported across different promotions** in the store, regardless of their statuses and validity dates. However, **duplicate codes cannot be created within the same promotion**. This means that shoppers can apply a single coupon code to trigger multiple promotions if those promotions share common coupon codes. Codes that share the same name can serve different purposes. For example, one code may have `per_application` with a limited number of uses, while another identical code can have `per_checkout` with unlimited use. **Duplicate Code Handling:** - If a duplicate code is detected **within the same promotion**, the request will return a `422 Duplicate code` error. - When creating duplicate codes, a message appears with the successful response indicating the duplication. Please refer to the **OpenAPI examples** section on this page for sample request structures. Request --- ## Create a Rule Promotion Job import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Creates an asynchronous job for a specific Rule Promotion. Jobs are used to generate or export promotion codes in bulk. The following job types are supported: - **`code_generate`**: Generates a batch of unique promotion codes. - **`code_export`**: Exports all existing promotion codes as a downloadable CSV file. Job processing occurs asynchronously. The job request is queued, and its status must be checked separately. ### Job Processing Status Jobs can have the following statuses: - `pending`: Job is in the queue, waiting to be processed. - `processing`: Job is actively being processed. - `completed`: Job completed successfully. - `failed`: Job encountered an error and did not complete. - `cancelling`: Cancellation in progress (for long-running jobs). - `cancelled`: Job was successfully cancelled. Please refer to the **OpenAPI examples** section on this page for sample job creation requests. Request --- ## Create a Rule Promotion import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Creates a new rule-based promotion, allowing flexible discount strategies based on cart or item conditions. Promotions can apply fixed or percentage-based discounts, apply automatically or via codes, and have eligibility rules based on product attributes, cart total, SKU conditions, custom attributes, and more. This endpoint supports a variety of promotion types, such as: - **Cart-wide discounts** - **Item-specific discounts** - **Shipping discounts** - **Combinations thereof** :::note The minimum item discount amount is zero, both for amounts and percentages. A store can have a maximum of **50 active and future automatic rule promotions**. ::: Request --- ## Delete Rule Promotion Codes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes one or more promotion codes from a specific rule promotion. - Supports **bulk deletion**, allowing multiple codes to be removed in a single request. - Removes promotion codes permanently, making them unavailable for future use. - If a code has already been redeemed, it will be removed from the system but may still reflect in historical transactions. A successful request returns a `204 No Content` response, indicating the specified promotion codes have been deleted. Request --- ## Delete a Rule Promotion import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes an existing Rule Promotion identified by its promotion ID. - This action **permanently removes** the promotion and cannot be undone. - If the promotion is active, please ensure that its removal does not impact ongoing campaigns. A successful request returns a `204 No Content` response, indicating that the promotion has been deleted. Request --- ## Delete A Single Rule Promotion Code import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes a single promotion code from a specific rule promotion. - Permanently removes the specified promotion code, making it unavailable for future use. - Can be used to **revoke a specific code** without affecting other codes under the same promotion. - If the code has already been redeemed, it will still be removed from the system but may still reflect in historical transactions. A successful request returns a `204 No Content` response, indicating the specified promotion code has been deleted. Request --- ## Get a Rule Promotion by ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a single Rule Promotion by the promotion ID. Responses include promotion specifications such as discount type, eligibility criteria, and configuration details. Request --- ## Get Rule Promotion Code Usages import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of usage records for a specific Rule Promotion code. - Provides insights into how many times a specific code was used. - Can be filtered and paginated to refine results. - Useful for tracking the performance of individual promotion codes. Request --- ## Get Rule Promotion Codes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the list of promotion codes associated with a specific Rule Promotion. - Returns all codes generated for the given promotion ID, including details on usage limits and redemption status. - Supports both automatically generated and manually created promotion codes. - Can be used to verify whether a promotion code is still valid or has reached its usage limit. Request --- ## Get Rule Promotion Code Exported File import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the exported promotion codes for a rule promotion job in a CSV format. - The file contains the generated codes along with relevant metadata. - This endpoint is applicable only for jobs of type `code_export`. - The job must be in a `completed` state before the file can be retrieved. Request --- ## Get Rule Promotion Jobs import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of jobs associated with a specific rule promotion. Each job represents an asynchronous operation such as promotion code generation or export. The response includes details such as: - **Job type** (`code_generate` or `code_export`) - **Job status** (`pending`, `processing`, `completed`, `failed`, `cancelling`, or `cancelled`) - **Parameters used** (such as number of codes generated) - **Results** (such as number of codes successfully generated or deleted) ### Filtering You can filter jobs by: - **Job Type** (`eq(job_type, code_export)`) - **Status** (`eq(status, complete)`) Request --- ## Get Rule Promotion Usages import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of usage records for a specific Rule Promotion. - Provides details about when and how a promotion was used. - Can be filtered and paginated to refine results. - Useful for analyzing promotion effectiveness and customer engagement. Request --- ## Get Rule Promotions import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of rule-based promotions, including information such as discount type, eligibility criteria, and configuration details. This endpoint supports filtering to refine results based on specific promotion attributes. Use query parameters to filter promotions by: - **Code** – Retrieve a specific promotion by its code. - **Promotion name** – Search for promotions by name. - **Activation status** – Filter by whether a promotion is active or not. - **Stackability** – Identify promotions that can or cannot be combined with others. - **Start and end dates** – Retrieve promotions based on their validity periods. Request --- ## Rule Promotions API import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Rule Promotions provide the flexibility to offer diverse discounts to shoppers. This functionality supports discounts of varying complexities, from code-based customer discounts, to "Buy X Get Y" scenarios, fixed price promotions, and more based on your business needs. You can create a Rule Promotion using the Rule Promotions API or through the Promotions Builder in Commerce Manager. To apply Rule Promotions in carts and orders across an entire store, please enable the `use_rule_promotions` configuration in Cart Settings. You can also update a specific cart to use Rule Promotions by updating the cart's specific discount settings. Please see [Update A Cart](/docs/api/carts/update-a-cart) for more details. Enabling Rule Promotions enacts Hybrid Mode, allowing simultaneous use of both Promotions Standard and Rule Promotions discounts. For example, let's say a store provides the following promotions: - A Promotions Standard discount for 10% off the shopping cart - A Rule Promotion offering for a 20% discount on the shopping cart If a cart qualifies for both discounts based on the respective eligibility criteria, the system applies both types of discounts to the shopping cart, starting with Promotions Standard definitions before applying Rule Promotions. In this case, the application results in a 10% discount from the Promotions Standard definition and a 20% discount from the Rule Promotion. ### Rule Set A rule set is the criteria that determine when and how promotions get applied. Rule Sets consist of rule conditions and corresponding actions, which define eligibility and application details, respectively. Rule Sets may also contain targeted catalogs and currencies for further application granularity. **Example** Buy an apple, get an orange 50% off. Here, buying an apple is the rule and the 50% discount on an orange is the action. #### Rules Rules describe the conditions necessary for promotion eligibility. In our apple-orange example above, the rule indicates the shopper must buy an apple to get the discount on an orange. In other words, the buying of an apple is the condition which determines eligibility for the corresponding discount. **Condition Architecture:** All conditions follow a consistent structure with three primary components: - **`strategy`**: Defines the type of condition (e.g., `cart_total`, `item_category`) - **`operator`**: Specifies how the condition is evaluated (e.g., `gte`, `in`, `contains_all`) - **`args`**: Contains the values to evaluate against Some conditions support additional components for complex scenarios: - **`children`**: Sub-conditions that provide additional specificity - **`condition`**: Used in actions to define item-specific restrictions **Condition Categories:** - **Cart-level**: Evaluate entire cart properties (total, custom attributes) - **Account-level**: Consider customer account characteristics (tags, segments) - **Item-level**: Target specific products, categories, or attributes - **Bundle conditions**: Complex multi-item requirements for "Buy X, Get Y" scenarios - **Logical operators**: AND/OR logic for sophisticated eligibility rules **Key Design Considerations:** - **Performance**: Order conditions from most to least restrictive for optimal evaluation - **Maintainability**: Use `item_identifier` instead of legacy `item_sku`/`item_product_id` strategies - **Complexity**: Limit nesting depth and consider evaluation costs for complex bundle conditions - **Business Logic**: Ensure condition combinations align with promotion goals and margin requirements #### Actions Actions describe how discounts apply to eligible carts and orders. These signify the discount type, level, configurations, and any limitations or restrictions when applying. Actions can also include: - Action conditions: specify which items should be included or excluded when applying the discounts. These can be based on factors such as item SKUs, product attributes, quantities, or categories. - Action limitations: impose restrictions on the number of products eligible for discounts, maximum discount amounts, and/or total applications for discounts. In the apple-orange example, the action denotes the system applies a 50% discount to an orange, assuming the eligibility rules are met. For more complex scenarios, the action might say to provide a 50% discount on up to three oranges or might provide a fixed $1 discount on the two most expensive items from the "fruit" category. :::note For promotions that include a mix of item and cart rules or actions, we recommend including the specific item conditions in all item strategies to ensure desired discount applications. For complex promotions in general, we recommend including specific item conditions on all item strategies to ensure the appropriate items receive discounts. Please see the [Create a Rule Promotion API Request Examples](/docs/api/promotions-builder/create-rule-promotion) for more details on specifying conditions, restrictions, and inclusions. ::: #### Action Limitations Action limitations define constraints or rules that govern how a promotion's action is applied. While actions specify what discount is given (e.g., 10% off the cart), limitations control how much, to which items, and under what circumstances that action is applied. Limitations include: - **`max_discount`**: Caps the total value of the discount. - **`max_quantity`**: Limits the number of discounted units per item. - **`items`**: Restricts how many and which items are eligible, and in what order (e.g., max_items, price_strategy). - **`max_items`**: Specifies the maximum number of items eligible for the discount. - **`price_strategy`**: Determines how eligible items are selected based on price: - **Cheapest (default)**: The discount is applied to the cheapest item(s) in the cart. - **Expensive**: The discount applies to the most expensive item(s) in the cart. Some limitations, like auto_add, influence the application behavior of the action rather than its scope. - **`auto_add`**: Automatically adds items to the cart once conditions are met, providing additional configuration for the promotion’s application mode. - **`show_suggestions`**: A flag indicating whether to show suggestions for eligible items in the cart if the item is not in the cart. In this way, limitations can affect either the scope of the discount or the manner in which it is applied, providing both technical and user-facing boundaries around a promotion’s behavior. For example, consider a **50% discount on items from a category**, with the following limitations: - **Applies to a maximum of two items (`max_items: 2`)** - **Only applies to the two cheapest eligible items (`price_strategy: cheapest`)** - **Limits the total discount to $10 (`max_discount: 1000`)** - **Ensures a maximum of two units per eligible item receive the discount (`max_quantity: 2`)** #### Catalogs and Currencies As part of the Rule Set, you can also specify the catalogs and currencies for a given Rule Promotion. With catalogs defined, the promotion only considers items from the identified catalogs and therefore will not consider custom items or items from other catalogs. With no catalogs defined, the promotion considers all items, including custom items. Specifying a currency for a Rule Promotion restricts it to carts using that currency. Rule Promotions support multiple currencies when using a percent discount. If no currencies are defined, the discount applies to carts in any currency. ### Building Blocks #### Strategies Strategies describe the types of condition criteria or application actions used to build a promotion. A given promotion can be comprised of several strategies in its rules and actions. These might include several instances of similar strategies, different strategies, or some combination thereof. Think of these as building blocks that can be applied together to provide a functional discount. - Rule strategies define the types of conditions that need to be met for eligibility. These might include cart total amount, item prices, cart custom attributes, and more. - Action strategies refer to the type of action execution run when the eligibility criteria are met. For actions, the possible strategies are `cart_discount`, `item_discount`, `item_bundle_discount` and `shipping_discount`. For more information, please see [Promotions Builder API Overview](/docs/promotions-builder/promotions-builder-api/promotions-builder-api-overview). #### Operators and Args Operators determine how to evaluate a given strategy, while `args` define the value threshold to measure against. For example, please consider the following condition strategy: ``` { "strategy": "cart_total", "operator": "gte", "args": [ 10000 ] } ``` In this example, the strategy is `cart_total`, telling the system to assess eligibility based on the total cart value. The operator is a greater-than-or-equal-to (`gte`) evaluation, indicating the candidate value (in this case, cart total) becomes eligible once it reaches or exceeds the threshold. Finally, the `args` value provides the threshold value to compare against, 10000. Taken together, then, this strategy looks for cart totals greater than or equal to 10000. ::: note Different strategies support different operators. For more information, please see [Rule Promotions API Overview](/docs/promotions-builder/promotions-builder-api/promotions-builder-api-overview). ::: #### Children and Sub-Conditions For additional promotion granularity, some strategies support additional specifications via `children` and `condition` fields. These fields contain strategies, which provide further specifications around their parent strategy evaluations. In other words, sub-conditions refer to additional criteria or conditions that must be met for a particular promotion to be applied. The following strategies support children/sub-conditions: - `item_price` - `item_quantity` - `item_category` - `item_attribute` - `and` - `or` Notably, when multiple sub-condition siblings exist, they are combined together, such that all sub-conditions must be met to fulfill eligibility. ### Stacking Promotion stacking and priority are key elements in managing discounts, ensuring promotions are applied as intended. Stacking allows multiple promotions to be applied to a single cart, either targeting the same items or different ones. The `stackable` flag determines whether a promotion can stack with others, defaulting to `true`. If set to `false`, no other promotion can stack on top, and the highest-priority promotion takes precedence. Priority settings dictate the order in which promotions are applied, with higher numbers indicating higher priorities. By default, promotions without assigned priorities are applied in reverse order of creation, with newer promotions applied first and calculated against any existing discounted prices. Hybrid Mode enables the coexistence of Standard Promotions and those configured in the Promotions Builder, with each functioning independently. This means Standard Promotions can stack alongside non-stackable Builder promotions, and their stackability and priority settings remain unaffected by Standard Promotions. Override stacking, set using the `override_stacking` flag, provides an additional layer of control over how promotions interact. This flag determines whether the promotion can stack with other promotions that are typically non-stackable and defaults to `false` when not set. When set to `true`, the promotion can stack with promotions configured as non-stackable, unless those non-stackable promotions also override stacking. ### Shipping Rule Promotions support shipping discounts, identified by the corresponding strategies during promotion creation. Shipping discounts apply to shipping group base prices and do not impact shipping taxes or configured shipping fees. Please see [Shipping Groups](/docs/ship-groups/shipping-groups/index) for more information on creating and interacting with shipping groups. ### Items Bundle You can promote and discount groups of items together using the `items_bundle` rule strategy and the `items_bundle_discount` action strategy. When these strategies are applied, the cart must contain items that meet all specified criteria to qualify for the discount. - The `items_bundle` rule strategy defines the required group of items for discount eligibility. - The `items_bundle_discount` action strategy specifies how the discount is applied to the qualifying group. - The `items_bundle` strategy requires **at least one** requirement that defines which items are eligible. Bundle items can be mixed across categories or attributes to form a valid bundle. - The `item_quantity` can be used with any of the bundling strategies, including `item_category`, `item_identifier`, `item_attribute`, etc. - `item_quantity` only support `eq` operator when configuring `items_bundle` strategy. - For instance, targeting a category with `item_quantity` with operator `eq` 2 means any two items from that category can form a bundle. The system will prioritize individual line items with sufficient quantity first before combining quantities of separate line items. ``` { "strategy": "items_bundle", "children": [ { "strategy": "and", "children": [ { "strategy": "item_category", "operator": "in", "args": [ "667d9fae-d8c7-4941-b556-70cb4b8612f1" ] }, { "strategy": "item_quantity", "operator": "gte", "args": [ 2 ] } ] } ] } ``` - When using `item_quantity` to target specific items or categories, the required quantity can be fulfilled by a combination of eligible items. - For example, if the rule is `item_quantity` with operator `eq` 3 for products in the "Office Supplies" category, the discount will apply when the cart includes any of the following combinations: - 2 packs of printer paper + 1 box of pens - 1 stapler + 2 notepad - 1 box of pens + 1 notepad + 1 pack of printer paper - 3 identical items, such as 3 boxes of pens - **Please Note**: the system considers line items sequentially based on their quantities, using the order of addition to the cart as a fallback tie-breaker. If the first eligible item has sufficient quantity to fulfill the bundle criteria, it will consume the required quantity and complete the evaluation for that criteria. The system does not re-evaluate these processed items to share any remaining quantities with other items. This behaviour may result in differing total discount amounts for two shopping carts with the same items added in a different order if those items have the same quantity values. Available discount types: - `fixed_price` – Sets a fixed total price for the group (e.g., If the fixed price is set at $100, then the group's subtotal is exactly $100) - `percent` – Applies a percentage-based discount to the group. - `fixed` – Deducts a fixed amount from the group's total price. Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: URL: [https://elasticpath.com](https://elasticpath.com) License MIT --- ## Update a Rule Promotion import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Updates an existing Rule Promotion specified by its promotion ID. This includes both **semantic and syntactic validation** to ensure correctness. For example, the start date must be earlier than the end date. Editable fields include: - `name` - `description` - `enabled` - `start` - `end` - `automatic` - `stackable` - `override_stacking` - `rule_set` :::note When updating the `automatic` field from `false` to `true`, the store must not exceed the maximum limit of **50 active and future automatic rule promotions**. ::: Request --- ## Administrator Latest Releases Catalog API Use the Administrator Latest Releases Catalog View API to retrieve product, hierarchy and node information. :::danger The Administrator Latest Releases Catalog View API is for Administrator use only. Do not use these endpoints on your customer-facing frontends. ::: Publishing a catalog creates a release of that catalog that you can use in an organization or in a specific store or other shopper experience. You can retrieve the hierarchies, nodes, and the `live` products associated with a catalog release. You can see which parent nodes a product is associated with. This is useful if want to improve how your shoppers search your store, for example. Currently, published catalogs are limited to the current release and two releases prior to the current release. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Catalogs Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Use the catalog-view Service API to create your catalogs. You also have the flexibility to create catalogs for different scenarios by combining hierarchies of products with a price book. Scenarios might include: - Multiple geographical regions. Display different catalogs in different regions with suitable pricing or combine product hierarchies from two different regions to display in a third region. - Multiple channels. Display different catalogs based on how a shopper accesses your store, such as through a mobile app or a web storefront. - Direct to business versus direct to customers. Offer different products and prices for business customers versus retail customers. - Preferred customers. Offer special pricing to preferred customers while displaying a standard price catalog to all other shoppers. - Reward programs. Enable reward programs where catalog prices drop after a certain spending level is reached. - Product sales. Offer sale items for a limited time. Scenarios are created by defining the context within which a catalog is displays. Contexts can be a customer ID, a channel, or any other user-defined tag that can be passed to the APIs from the front-end shopper experiences. Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Catalogs A catalog contains the products available for sale either in your organization or store. A catalog also contains information about how to organize those products for navigation menus and search facets in a shopper experience. Before you create a catalog you must define the following resources: - Hierarchies: hierarchies and nodes to categorize the products. See [**Hierarchies**](/docs/api/pxm/products/hierarchies). - Products: product information, associated assets, and links to hierarchy nodes. See [**Products**](/docs/api/pxm/products/products). - Price Books: prices for the products associated with the hierarchies. See [**Price Books**](/docs/api/pxm/pricebooks). A catalog is a combination of hierarchies and a price book. ### Products Commerce automatically assigns types to the products you create. Product types can be used in catalogs. For example, in your catalog, you can filter on `parent` so that only your parent products are displayed in your storefront. You can use product tags to store or assign a key word against a product or service that you sell in your store. The product tag can then be used to describe or label that product. Product tags represent similarities between products who do not share the same attributes. Using product tags means that you can group your products together, for example, by brand, category, subcategory, colors, types, industries, and so on. Product tags can be used in catalogs. For example, you can categorize your products based on color. Your shoppers can then search your products by color, enabling shoppers to quickly find what they are looking for, increasing the likelihood of a purchase, and boosting conversion rates. ### Hierarchies The hierarchies determine which products appear in the catalog, that is, only the products that are associated with the selected hierarchies are included in the catalog. You can also specify the order you want your hierarchies to display in a published catalog. You can order your hierarchies on a catalog-by-catalog basis. ![Hierarchy_sorting](/assets/hierarchy_sorting.png) For more information, see [**create a Catalog**](/docs/api/pxm/catalog/create-catalog). #### Understanding How Products And Nodes Are Associated You can use `breadcrumb` metadata to understand how products and nodes are associated. it explains how products are associated with parent nodes and the relationship among the array of nodes. This is useful if you want to improve how your shoppers search within your store. The `breadcrumb` information that you get in an endpoint response depends on whether the endpoint is retrieving product or node details. | Object | Product/Node | Description | | --- | --- | --- | | `breadcrumb` | Node | A list of nodes that a product is associated with. Up to 10 levels of nodes are displayed, depending on the number of levels of nodes you have. | | `bread_crumbs` | Product | The relationship among the array of nodes a product is associated with, demonstrating the linking of the children nodes with the parent nodes. Up to 10 levels of nodes are displayed, depending on the number of levels of nodes you have. | | `bread_crumb_nodes` | Product | An array of parent node IDs that a product is associated with. The `bread_crumb_node` metadata lists up to 10 levels of parent nodes, depending on the number of levels of parent nodes you have. | #### Understanding `bread_crumbs` Metadata The following diagram illustrates a parent and child nodes. ![Breadcrumbs](/assets/breadcrumbs.PNG) 1. The product is in **Node 2**. The ID for **Node 2** is shown first in the first set of breadcrumbs. 1. **Node 2** is part of **Hierarchy 1**. The ID for **Hierarchy 1** is shown second. 1. **Node 1** is the parent node of **Node 2**. The ID for **Node 1** is shown last. 1. The product is also in **Node 3**. The ID for **Node 3** is shown first in the second set of breadcrumbs. 1. **Node 3** is in the root of **Hierarchy 1**. The ID for **Hierarchy 1** is shown last. In the `bread_crumb_nodes` metadata, you can see a list of parent nodes a product is associated with. If you subsequently add a product to a new node, then the `bread_crumb_nodes` metadata appends the new node to the top of the list. Using the example above, if we add the product to **Node 1**: 1. The `bread_crumb_nodes` metadata is generated to show the new node appended to the top of the list. 1. The `bread_crumbs` metadata is updated with the new node. #### Understanding Breadcrumb Metadata for Child Products When a catalog is published, the breadcrumb information for a child product includes the metadata mentioned for the parent product, in addition to the information specific to the child product. For example, **Product A** is the parent product, associated with **Node 1** and **Node 2**. The metadata for child **Product B** includes **Node 1** and **Node 2**, in addition to its own metadata information. ### Nodes The nodes determine which products appear under this in the catalog, that is, only the products that are associated with the selected node are shown under this node. ### Price books A price book contains the prices for each of the products in the catalog. You can create multiple price books for different scenarios, such as seasonal sales, business versus retail customer pricing, and reward programs. When creating a catalog, you can specify up to five price books. You must set a priority for your price books. Product prices are displayed in the catalog according to the priority of the price books. See [Create a catalog](/docs/api/pxm/catalog/create-catalog). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Configure a Shopper Bundle import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Once you have configured your product bundles, you can display them in your storefront in your published catalog. Depending on how you have configured the minimum and maximum values for the product options in your components, you can allow your shoppers to choose which products they want to select. For example, you can enable a shopper to select 1 or more product options from a list of 10, giving your shoppers greater flexibility when selecting products in your store front. - Products must be in a `live` status. - If you have not specified any minimum or maximum values for the product options in your components, your shoppers can select any combination of product options. If you have configured minimum and maximum values using [Create a Bundle](/docs/api/pxm/products/create-product), this becomes part of the `bundle_configuration`. You can check how your bundle is configured using [Get a product in a catalog release](/docs/api/pxm/catalog/get-product) in `bundle_configuration` under `meta`. The `bundle_configuration` forms the body of the request. The response updates the `bundle_configuration` with the product options the shopper selects. The `meta` data is updated with the `meta` data of the selected product options. In your storefront, you could display this as a summary of the product options a shopper has selected. ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. | See [**Including Resources**](/guides/Getting-Started/includes). Request --- ## Creates a new catalog import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Before you create a catalog, you must define the following resources: - Hierarchies - hierarchies and nodes to categorize the products. - Products - product information, associated assets, and links to hierarchy nodes. - Price Books - prices for the products associated with the hierarchies. You can create multiple price books for different scenarios, such as seasonal sales, business versus retail customer pricing, and reward programs. When creating a catalog, you can specify up to five price books. You must configure a priority for your price books. Product prices are displayed in the catalog according to the priority of the price books. Priority is a number and the price book with the highest number has the highest priority. Request --- ## Creates a new catalog rule import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; If you have multiple catalogs, create catalog rule resources. With catalog rules, you can display different catalogs to different shoppers. For example, you can display a preferred pricing catalog to a few special customers. Or you can display one catalog to shoppers using your website and a different catalog to shoppers using your mobile app. Finally, you can define custom criteria by creating tags. :::note - If you have one catalog for all customers and channels, you can omit creating this resource. - Due to the way catalogs are cached in Commerce, using catalog rules to display catalogs sometimes causes a 5-minute time delay before the catalogs are displayed. - You cannot create catalog rules for organization catalogs. ::: For ideas about the kinds of business scenarios you can achieve with catalog rules, see [Catalog Rules](/docs/api/pxm/catalog/rules). To understand how catalogs are matched to shoppers by using rules, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). Request --- ## Deletes a catalog import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes an unpublished catalog. Use [**Delete a Release**](/docs/api/pxm/catalog/delete-release-by-id) and [**Delete All Releases**](/docs/api/pxm/catalog/delete-releases) to delete releases of a catalog. If the catalog is associated with any catalog rules, you must first update the catalog rules to remove the catalog. Request --- ## Deletes a release import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes the specified published catalog release. Request --- ## Deletes all releases import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes all releases of the specified published catalog. Request --- ## Deletes a catalog rule import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes a catalog rule Request --- ## Get all Hierarchies import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the hierarchies from a published catalog. :::note Currently, published catalogs are limited to the current release and two releases prior to the current release. ::: ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). | Operator | Description | Supported Attributes | Example | |:--- |:--- |:--- |:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, `slug`| `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. | `id` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get all Nodes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the child nodes from a published catalog. :::note Currently, published catalogs are limited to the current release and two releases prior to the current release. ::: You can see the parent nodes a node is associated with in the `breadcrumbs` metadata for each node. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). In a catalog, you can use a filter to return a list of nodes in a hierarchy structure that a product belongs to. You can use this to build breadcrumbs in your storefront. See [Building breadcrumbs in a storefront](#building-breadcrumbs-in-a-storefront). The response lists the products associated with the nodes. If products are [curated](/guides/How-To/Products/curating-products), they are displayed in `curated_products`. Product curation allows you to promote specific products within each of your hierarchies, enabling you to create unique product collections in your storefront. - If you don't provide any `curated_products`, products are listed by their `updated_at` time in descending order, with the most recently updated product first. - If you configure `curated_products` for only a few products, the curated products are displayed first and the other products are displayed in the order of `updated_at` time. - You can only curate 20 products or less. You cannot have more than 20 curated products. - If a curated product is removed from a node, the product is also removed from the `curated_products` list. - A product that is curated has the `"curated_product": true` attribute displayed. ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available. | Operator | Description | Attributes | Example | | --- | --- | --- | --- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, `slug` | `filter=eq(name,some-name)` | | `in` | Checks if the values are included in the specified string. If they are, the condition is true. | `Id` | `filter=in(id,9214719b-17fe-4ea7-896c-d61e60fc0d05,e104d541-2c52-47fa-8a9a-c4382480d97c,65daaf68-ff2e-4632-8944-370de835967d)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get all Products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the products from a published catalog. Only the products in a `live` status are retrieved. Currently, published catalogs are limited to the current release and two releases prior to the current release. You can see the parent nodes a product is associated with in the `bread_crumbs` and `bread_crumb_nodes` metadata for each product. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). The `variations` object lists the variation IDs and variation option IDs and their corresponding product IDs that are generated when the variation and variation options are built with a product. The `variations` object can then be added to your catalogs. By default, variations and variation options are sorted randomly. You can use the `sort_order` attribute to sort the order of your variation and variation options in `variations`. Once a parent product is published in a catalog, the [Get a List of products in a catalog release](/docs/api/pxm/catalog/get-all-products) response displays the sorted variations and variation options. Variations and variation options are displayed in descending order according to their `sort_order` values. ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. See [**Including Resources**](/guides/Getting-Started/includes). ### Filtering This endpoint supports filtering. For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available when filtering on this endpoint. | Operator | Description | Supported Attributes | Example | |:---|:------------------------------------------------------------------------------------------------|:---------------------------------------------------------|:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. For `product_types`, you can only specify one product type. For example, `filter=eq(product_types,child)`. | `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. For `product_types`, you can specify more than one product type. For example, `filter=in(product_types,child,bundle)`. | `id`, `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get all Related Products of a Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns related products of the provided product ID from a published catalog. Request --- ## Get all Hierarchies(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns all hierarchies from a catalog. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. For information about how rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). | Operator | Description | Supported Attributes | Example | |:--- |:--- |:--- |:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, `slug`| `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. | `id` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get all Nodes(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns all nodes in the catalog. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. For information about how rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). You can see the parent nodes a node is associated with in the `breadcrumbs` metadata for each node. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). In a catalog, you can use a filter to return a list of nodes in a hierarchy structure that a product belongs to. You can use this to build breadcrumbs in your storefront. For more information, see [Building breadcrumbs in a storefront](#building-breadcrumbs-in-a-storefront). The response lists the products associated with the nodes. If products are [curated](/guides/How-To/Products/curating-products), they are displayed in `curated_products`. Product curation allows you to promote specific products within each of your hierarchies, enabling you to create unique product collections in your storefront. - You can only curate 20 products or less. You cannot have more than 20 curated products. - If a curated product is removed from a node, the product is also removed from the `curated_products` list. ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available. | Operator | Description | Attributes | Example | | --- | --- | --- | --- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, `slug` | `filter=eq(name,some-name)` | | `in` | Checks if the values are included in the specified string. If they are, the condition is true. | `Id` | `filter=in(id,9214719b-17fe-4ea7-896c-d61e60fc0d05,e104d541-2c52-47fa-8a9a-c4382480d97c,65daaf68-ff2e-4632-8944-370de835967d)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get all Products(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the list of products from the catalog. Only the products in a live status are retrieved. ### Catalog Rules If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. If no catalog rules are configured, the first catalog found is returned. For information about how rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). ### Product and Node Associations You can see the parent nodes a product is associated within the `bread_crumbs` and `bread_crumb_nodes` metadata for each product. For example, this is useful if you want to improve how your shoppers search your store. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. | See [**Including Resources**](/guides/Getting-Started/includes). ### Filtering This endpoint supports filtering. For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available when filtering on this endpoint. | Operator | Description | Supported Attributes | Example | |:---|:------------------------------------------------------------------------------------------------|:---------------------------------------------------------|:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. For `product_types` and `tags`, you can only specify one. For example, `filter=eq(product_types,child)`. | `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. For `product_types` and `tags`, you can specify more than one. For example, `filter=in(product_types,child,bundle)`. | `id`, `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get all Related Products of a Product(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns related products of the provided product ID from a catalog. Request --- ## Get a Node's Children import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the child nodes for a node in the catalog. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. For information about how rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). You can see which parent nodes a node is associated with in the `breadcrumbs` metadata for each node. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). The response lists the products associated with the nodes. If products are [curated](/guides/How-To/Products/curating-products), they are displayed in `curated_products`. Product curation allows you to promote specific products within each of your hierarchies, enabling you to create unique product collections in your storefront. - If you don't provide any curated_products, products are listed by their updated_at time in descending order, with the most recently updated product first. - If you configure curated_products for only a few products, the curated products are displayed first and the other products are displayed in the order of updated_at time. - You can only curate 20 products or less. You cannot have more than 20 curated products. - A product that is curated has the "curated_product": true attribute displayed. - If a curated product is removed from a node, the product is also removed from the curated_products list. ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available. | Operator | Description | Attributes | Example | | --- | --- | --- | --- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, `slug` | `filter=eq(name,some-name)` | | `in` | Checks if the values are included in the specified string. If they are, the condition is true. | `Id` | `filter=in(id,9214719b-17fe-4ea7-896c-d61e60fc0d05,e104d541-2c52-47fa-8a9a-c4382480d97c,65daaf68-ff2e-4632-8944-370de835967d)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get a Parent Product's Child Products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; For a specified product and catalog release, retrieves a list of child products from a parent product. Any product other than a base product results in a `422 Unprocessable Entity` response. Only the products in a `live` status are retrieved. If you have multiple catalog rules defined, the rule that best matches the shopperʼs context is used to determine which catalog is retrieved. If no catalog rules are configured, the first catalog found is returned. For information about how rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). You can see the parent nodes a product is associated within the `breadcrumbs` metadata for each product. For example, this is useful if you want to improve how your shoppers search your store. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). ### Filtering This endpoint supports filtering. For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available when filtering on this endpoint. | Operator | Description | Supported Attributes | Example | |:---|:------------------------------------------------------------------------------------------------|:---------------------------------------------------------|:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. For `product_types` and `tags`, you can only specify one. For example, `filter=eq(product_types,child)`. | `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. For `product_types` and `tags`, you can specify more than one. For example, `filter=in(product_types,child,bundle)`. | `id`, `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. | See [**Including Resources**](/guides/Getting-Started/includes). Request --- ## Get a Bundle's Component Products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; With Product Experience Manager, you can [create](/docs/api/pxm/products/create-product) and manage bundles. A bundle is a purchasable product, comprising of one or more products that you want to sell together. You can create multiple components within a bundle. Each component must have at least one or more options. Each option is a product and a quantity. This endpoint returns a list of component product IDs for the specified bundle. Request --- ## Get a Hierarchy's Children import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the parent nodes for the specified hierarchy. ![Parent Nodes](/assets/rootnodes.PNG) If you have multiple catalog rules defined, the rule that best matches the shopperʼs context is used to determine which catalog is retrieved. For information about how rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). In the `breadcrumbs` metadata, you can identify the parent nodes that a node is associated with. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). ### Filtering The following operators and attributes are available when filtering on this endpoint. | Operator | Description | Supported Attributes | Example | |:--- |:--- |:--- |:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, `slug`| `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. | `id` | `filter=in(id,some-id)` | For more information, see [Filtering](/guides/Getting-Started/filtering). ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get a Hierarchy's Nodes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns all the nodes for the specified hierarchy. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. For information about how rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). In the `breadcrumbs` metadata, you can identify the parent nodes that a node is associated with. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). | Operator | Description | Supported Attributes | Example | |:--- |:--- |:--- |:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, `slug`| `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. | `id` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get a Hierarchy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns a hierarchy from the catalog. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog to retrieve. For information about how catalog rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules). Request --- ## Get a Node import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns a node from the catalog. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. For information about how rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). You can see the parent nodes a node is associated with in the `breadcrumbs` metadata for each node. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). The response lists the products associated with a node. If products are [curated](/guides/How-To/Products/curating-products), they are displayed in `curated_products`. Product curation allows you to promote specific products within each of your nodes, enabling you to create unique product collections in your storefront. - If you don't provide any `curated_products`, products are listed by their `updated_at` time in descending order, with the most recently updated product first. - If you configure `curated_products` for only a few products, the curated products are displayed first and the other products are displayed in the order of `updated_at` time. - You can only curate 20 products or less. You cannot have more than 20 curated products. - A product that is curated has the `"curated_product": true` attribute displayed. - If a curated product is removed from a node, the product is also removed from the `curated_products` list. Request --- ## Get a Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the specified product from the catalog. The product must be in the `live` status. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. For information about how rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). You can see the parent nodes a product is associated with in the `bread_crumbs` and `bread_crumb_nodes` metadata for each product. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. | See [**Including Resources**](/guides/Getting-Started/includes). Request --- ## Get a Hierarchy's Products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the products associated with the specified hierarchy in the catalog. The products must be in the live status. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. See [Resolving catalog rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). You can see the parent nodes a product is associated with in the `bread_crumbs` and `bread_crumb_nodes` metadata for each product. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). ### Filtering This endpoint supports filtering. For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available when filtering on this endpoint. | Operator | Description | Supported Attributes | Example | |:---|:------------------------------------------------------------------------------------------------|:---------------------------------------------------------|:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. For `product_types` and `tags`, you can only specify one. For example, `filter=eq(product_types,child)`. | `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. For `product_types` and `tags`, you can specify more than one. For example, `filter=in(product_types,child,bundle)`. | `id`, `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | `files` | Optional | Any files associated with a product. | See [**Including Resources**](/guides/Getting-Started/includes). Request --- ## Get a Node's Products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the products associated with the specified hierarchy node in the catalog. The products must be in the `live` status. If the products have been curated then the products are returned in the order specified in the `curated_products` attribute. A product that is curated has the `"curated_product": true` attribute displayed. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. See [Resolving catalog rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). You can see the parent nodes a product is associated with in the `bread_crumbs` and `bread_crumb_nodes` metadata for each product. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). ### Filtering This endpoint supports filtering. For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available when filtering on this endpoint. | Operator | Description | Supported Attributes | Example | |:---|:------------------------------------------------------------------------------------------------|:---------------------------------------------------------|:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. For `product_types` and `tags`, you can only specify one. For example, `filter=eq(product_types,child)`. | `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. For `product_types` and `tags`, you can specify more than one. For example, `filter=in(product_types,child,bundle)`. | `id`, `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. | See [**Including Resources**](/guides/Getting-Started/includes). Request --- ## Get the catalog release as shoppers import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns a list of all published releases of the specified catalog. Request --- ## Get a catalog by ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the specified catalog. Request --- ## Gets all authorized catalogs import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all the catalogs that you are authorized to view. Currently, published catalogs are limited to the current release and two releases prior to the current release. You can see the differences between the last 2 consecutive catalog releases using the delta link returned in the response of a [publish a catalog](/docs/api/pxm/catalog/publish-release) endpoint. You can use the `is_full_delta` attribute returned from the `get a release of a catalog` endpoint to determine if you need to refresh the data in your company system before publishing a catalog release and injecting fresh data in a delta link. The `is_full_delta` attribute tells you if this is a full publish of a catalog release. Using a search service as an example, if the `is_full_delta` attribute is `true`, you should remove all data about that catalog from the search service before publishing a catalog release and injecting fresh data from the delta file. See [Publish a catalog](/docs/api/pxm/catalog/publish-release). If the `is_full_publish` attribute returned in the response is `false`, data from the previous catalog release overlaid the existing data in the delta file. The `is_full_publish` attribute is always `true` the first time a catalog is published. When determining whether delta data needs to be refreshed, ignore this attribute and always use the `is_full_delta` attribute. ### Filtering This endpoint supports filtering. For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available when filtering on this endpoint. | Operator | Description | Supported Attributes | Example | |:---|:------------------------------------------------------------------------------------------------|:---------------------------------------------------------|:--- | | `eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, | `filter=eq(name,some-name)` | | `in` | Checks if the values are included in the specified list. If they are, the condition is true. | `name` | `filter=in(name,some-name,some-name2)` | | `like` | Checks if the operand contains the specified string. Wildcards are supported | `name` | `filter=like(name,*some-name*)` | Request --- ## Get a Node's Children(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the child nodes for a node from a published catalog. :::note Currently, published catalogs are limited to the current release and two releases prior to the current release. ::: You can see the parent nodes a node is associated with in the `breadcrumbs` metadata for each node. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). In a catalog, you can use a filter to return a list of nodes in a hierarchy structure that a product belongs to. You can use this to build breadcrumbs in your storefront. For more information, see [Building breadcrumbs in a storefront](#building-breadcrumbs-in-a-storefront). The response lists the products associated with the nodes. If products are [curated](/guides/How-To/Products/curating-products), they are displayed in `curated_products`. Product curation allows you to promote specific products within each of your hierarchies, enabling you to create unique product collections in your storefront. - If you don't provide any `curated_products`, products are listed by their `updated_at` time in descending order, with the most recently updated product first. - If you configure `curated_products` for only a few products, the curated products are displayed first and the other products are displayed in the order of `updated_at` time. - You can only curate 20 products or less. You cannot have more than 20 curated products. - If a curated product is removed from a node, the product is also removed from the `curated_products` list. - A product that is curated has the `"curated_product": true` attribute displayed. ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available. | Operator | Description | Attributes | Example | | --- | --- | --- | --- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, `slug` | `filter=eq(name,some-name)` | | `in` | Checks if the values are included in the specified string. If they are, the condition is true. | `Id` | `filter=in(id,9214719b-17fe-4ea7-896c-d61e60fc0d05,e104d541-2c52-47fa-8a9a-c4382480d97c,65daaf68-ff2e-4632-8944-370de835967d)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get a Parent Product's Child Products(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; For a specified product and catalog release, retrieves a list of child products from a parent product. Any product other than a base product results in a `422 Unprocessable Entity` response. Only the products in a `live` status are retrieved. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. If no catalog rules are configured, the first catalog found is returned. For information about how rules are matched, see [Resolving Catalog Rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). You can see the parent nodes a product is associated within the breadcrumbs metadata for each product. For example, this is useful if you want to improve how your shoppers search your store. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). ### Filtering This endpoint supports filtering. For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available when filtering on this endpoint. | Operator | Description | Supported Attributes | Example | |:---|:------------------------------------------------------------------------------------------------|:---------------------------------------------------------|:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. For `product_types`, you can only specify one product type. For example, `filter=eq(product_types,child)`. | `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. For `product_types`, you can specify more than one product type. For example, `filter=in(product_types,child,bundle)`. | `id`, `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. | See [**Including Resources**](/guides/Getting-Started/includes). Request --- ## Get a Bundle's Component Products(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; With Product Experience Manager, you can [create](/docs/api/pxm/products/create-product) and manage bundles. A bundle is a purchasable product, comprising of one or more products that you want to sell together. You can create multiple components within a bundle. Each component must have at least one or more options. Each option is a product and a quantity. This endpoint returns a list of component product IDs for the specified bundle. ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. | See [**Including Resources**](/guides/Getting-Started/includes). Request --- ## Get a Hierarchy's Children(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the parent nodes for the specified hierarchy from a published catalog. ![Parent Nodes](/assets/rootnodes.PNG) :::note Currently, published catalogs are limited to the current release and two releases prior to the current release. ::: In the `breadcrumbs` metadata, you can identify the parent nodes that a node is associated with. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). | Operator | Description | Supported Attributes | Example | |:--- |:--- |:--- |:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, `slug`| `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. | `id` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get a Hierarchy's Nodes(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns all nodes for the specified hierarchy from a published catalog. :::note Currently, published catalogs are limited to the current release and two releases prior to the current release. ::: In the `breadcrumbs` metadata, you can identify the parent nodes that a node is associated with. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). | Operator | Description | Supported Attributes | Example | |:--- |:--- |:--- |:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. | `name`, `slug`| `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. | `id` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. Request --- ## Get a Hierarchy(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the specified hierarchy from a published catalog. :::note Currently, published catalogs are limited to the current release and two releases prior to the current release. ::: Request --- ## Get a Node(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns a node from a published catalog. :::note Currently, published catalogs are limited to the current release and two releases prior to the current release. ::: You can see the parent nodes a node is associated with in the `breadcrumbs` metadata for each node. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). The response lists the products associated with the nodes. If products are [curated](/guides/How-To/Products/curating-products), they are displayed in `curated_products`. Product curation allows you to promote specific products within each of your hierarchies, enabling you to create unique product collections in your storefront. - If you don't provide any `curated_products`, products are listed by their `updated_at` time in descending order, with the most recently updated product first. - If you configure `curated_products` for only a few products, the curated products are displayed first and the other products are displayed in the order of `updated_at` time. - You can only curate 20 products or less. You cannot have more than 20 curated products. - If a curated product is removed from a node, the product is also removed from the `curated_products` list. - A product that is curated has the `"curated_product": true` attribute displayed. Request --- ## Get a Product(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns a product from a published catalog. The product must be in `live` status. Currently, published catalogs are limited to the current release and two releases prior to the current release. ### Product and Node Associations in Breadcrumb Metadata You can see the parent nodes a product is associated with in the `bread_crumbs` and `bread_crumb_nodes` metadata for each product. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). ### Product Variations The `variations` object lists the variation IDs and variation option IDs and their corresponding product IDs that are generated when the variation and variation options are built with a product. The `variations` object can then be added to your catalogs. By default, variations and variation options are sorted randomly. You can use the `sort_order`attribute to sort the order of your variation and variation options in `variations`. Once a parent product is published in a catalog, the get a product in a catalog release response displays the sorted variations and variation options. Variations and variation options are displayed in descending order according to their `sort_order` values. ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. See [**Including Resources**](/guides/Getting-Started/includes). Request --- ## Get a Hierarchy's Products(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the products associated with the specified hierarchy in the catalog. The products must be in the `live` status. If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. See [Resolving catalog rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). You can see the parent nodes a product is associated with in the `bread_crumbs` and `bread_crumb_nodes` metadata for each product. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). The `variations` object lists the variation IDs and variation option IDs and their corresponding product IDs that are generated when the variation and variation options are built with a product. The variations object can then be added to your catalogs. By default, variations and variation options are sorted randomly. You can use the `sort_order` attribute to sort the order of your variation and variation options in variations. Once a parent product is published in a catalog, the [Get a List of products in a catalog](/docs/api/pxm/catalog/get-all-products) release response displays the sorted variations and variation options. Variations and variation options are displayed in descending order according to their `sort_order` values. ### Filtering This endpoint supports filtering. For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available when filtering on this endpoint. | Operator | Description | Supported Attributes | Example | |:---|:------------------------------------------------------------------------------------------------|:---------------------------------------------------------|:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. For `product_types`, you can only specify one product type. For example, `filter=eq(product_types,child)`. | `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. For `product_types`, you can specify more than one product type. For example, `filter=in(product_types,child,bundle)`. | `id`, `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. | See [**Including Resources**](/guides/Getting-Started/includes). Request --- ## Get a Node's Products(Catalog) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the products associated with the specified hierarchy node in the catalog. The products must be in the `live` status. If the products have been curated, then the products are returned in the order specified in the `curated_products` attribute. A product that is curated has the `"curated_product": true` attribute displayed. :::note Currently, published catalogs are limited to the current release and two releases prior to the current release. ::: If you have multiple catalog rules defined, the rule that best matches the shoppers context is used to determine which catalog is retrieved. See [Resolving catalog rules](/docs/api/pxm/catalog/rules#resolving-catalog-rules). You can see the parent nodes a product is associated with in the `bread_crumbs` and `bread_crumb_nodes` metadata for each product. This is useful if you want to improve how your shoppers search your store, for example. See [Product and Node Associations in Breadcrumb Metadata](/guides/How-To/Catalogs/breadcrumbs). The `variations` object lists the variation IDs and variation option IDs and their corresponding product IDs that are generated when the variation and variation options are built with a product. The `variations` object can then be added to your catalogs. By default, variations and variation options are sorted randomly. You can use the `sort_order` attribute to sort the order of your variation and variation options in `variations`. Once a parent product is published in a catalog, the [Get a List of products in a catalog release](/docs/api/pxm/catalog/get-all-products) response displays the sorted variations and variation options. Variations and variation options are displayed in descending order according to their `sort_order` values. ### Filtering This endpoint supports filtering. For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available when filtering on this endpoint. | Operator | Description | Supported Attributes | Example | |:---|:------------------------------------------------------------------------------------------------|:---------------------------------------------------------|:--- | | `Eq` | Checks if the values of two operands are equal. If they are, the condition is true. For `product_types` and `tags`, you can only specify one. For example, `filter=eq(product_types,child)`. | `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=eq(name,some-name)` | | `In` | Checks if the values are included in the specified string. If they are, the condition is true. For `product_types` and `tags`, you can specify more than one. For example, `filter=in(product_types,child,bundle)`. | `id`, `name`, `sku`, `slug`, `manufacturer_part_num`, `upc_ean`, `product_types`, `tags` | `filter=in(id,some-id)` | ### Building breadcrumbs in a storefront In a catalog, you can use the nodes directly attached to a product to build breadcrumbs in your storefront. This eliminates the need for additional queries to fetch hierarchy or parent node details. Each node contains all the necessary information in `breadcrumbs` metadata, such as its own details and the details of its parent hierarchy/node(s), to construct the complete breadcrumb path without requiring additional queries. An example is shown below: `filter=in(id,c83bfe55-0d87-4302-a86d-ab19e7e323f1,6003d7ef-84f3-49bb-a8bd-4cbfa203dcbb)` - Specify the node IDs directly attached to the product in the filter expression. - You can include as many node IDs as required. - It does not matter what order you specify the node IDs. The nodes are returned in the order they were last updated. ### Including Resources Using the `include` parameter, you can retrieve top-level resources, such as, files or main image, bundle component products and product attributes, such as SKU or slug. | Parameter | Required | Description | | :---------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `component_products` | Optional | The component product data and key attribute data, such as SKU or slug, to return for component products in a product bundle. | | `main_image` | Optional | The main images associated with a product. | | `files` | Optional | Any files associated with a product. | See [**Including Resources**](/guides/Getting-Started/includes). Request --- ## Get a catalog release by ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the specified catalog release. Request --- ## Gets all authorized catalog releases import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns a list of all published releases of the specified catalog. Currently, published catalogs are limited to the current release and two releases prior to the current release. You can see the differences between the last 2 consecutive catalog releases using the `delta` link returned in the response of a `publish a catalog` endpoint. You can use the `is_full_delta` attribute returned from the `get a release of a catalog` endpoint to determine if you need to refresh the data in your company system before publishing a catalog release and injecting fresh data in a delta link. The `is_full_delta` attribute tells you if this is a full publish of a catalog release. Using a search service as an example, if the `is_full_delta` attribute is `true`, you should remove all data about that catalog from the search service before publishing a catalog release and injecting fresh data from the delta file. If the `is_full_publish` attribute returned in the response is `false`, data from the previous catalog release overlaid the existing data in the delta file. The `is_full_publish` attribute is always `true` the first time a catalog is published. When determining whether delta data needs to be refreshed, ignore this attribute and always use the `is_full_delta` attribute. Request --- ## Get a catalog rule by ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a catalog rule by ID Request --- ## Gets all authorized catalog rules import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves all authorized catalog rules. ### Filtering This endpoint supports filtering. For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are supported. | Operator | Description | Supported Attributes | Example | |:--- |:--- |:--- |:--- | | `eq` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | `id`,`catalog_id`,`account_ids`,`customer_ids`,`channels`,`tags`,`pricebook_ids` | `filter=eq(id,some-id)` | | `in` | Checks if the values are included in the specified string. If they are, the condition is true. | `id`,`account_ids`,`customer_ids`,`channels`,`tags`,`pricebook_ids` | `filter=in(account_ids,some-id,another-id)` | Request --- ## Publishes a catalog import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Publishes a catalog. You must publish a catalog before you can retrieve that catalog in an organization or store. The hierarchies, live products, and prices associated with a published catalog are in read-only mode. If you make a change to these resources, for example, a change to your price book or hierarchies, you need to republish the catalog. You can get [a catalog release](/docs/api/pxm/catalog/get-release-by-id) to retrieve a published catalog. Currently, published catalogs are limited to the current release and two releases prior to the current release. You can see the differences between the last 2 consecutive catalog releases. This is useful if want to understand how your products have changed in your catalog, ensuring your site search integration is kept up-to-date. Once a catalog release has completed publishing, the delta relationship links to the delta document. The `delta` links are signed and only valid for 1 hour. Re-reading a catalog release, for example, using [Getting a release of a catalog](/docs/api/pxm/catalog/get-release-by-id) returns a fresh a link. You can use the `is_full_delta` attribute returned from the `get a release of a catalog` endpoint to determine if you need to refresh the data in your company system before injecting fresh data in a `delta` link. The `is_full_delta` attribute tells you if this is a full publish of the catalog. Using a search service as an example, if the `is_full_delta` attribute is `true`, you should remove all data about that catalog from the search service before injecting fresh data from the `delta` file. If the `is_full_delta` attribute is `false`, then data from the previous catalog overlays the existing data in the `delta` file. To publish a catalog and inject fresh data in a `delta` link, set `export_full_delta` to `true`. If a previous catalog publish date is greater than 90 days, then a full catalog publish is automatically performed. If you publish your catalogs infrequently, Commerce may perform a full publish when you are expecting a delta publish. :::caution Generating a full delta is resource intensive and slows down the publishing process and so should only be performed in certain circumstances, for example, when initializing an integration with a service like Algolia. ::: The `is_full_delta` attribute is always `true` the first time a catalog is published. The information is stored in a collection of `json` documents in a compressed file. You can either manually check the file or, for example, use them to automatically update another company system you may have. - Delta files are only available for 30 days. - Delta files are removed when a catalog release is deleted. Each document has a `delta_type` with one of the following values, depending on whether a product has been deleted, updated or created in a catalog release. - `delete` describes products deleted from this release of a catalog. - `createupdate` describes products updated in this release of a catalog. ### Multi-Store Management Solutions In a multi-store management solution. - You can create organization catalogs. Your organization catalogs are available for your stores to use. - Your stores can create their own catalogs. - Your stores can create catalogs that have a combination of organization products and store products. If you are publishing a catalog in a store that contains resources from an organization, in Commerce Manager, you must enable the **Include Organization Resources in Catalog Publishes** checkbox. 1. Go to **SYSTEM** > **Store Settings**. 2. Click **General Settings**. 3. Select **PXM** from the list. 4. Select the **Include Organization Resources in Catalog Publishes** checkbox. Request --- ## Releases When a catalog is published, a catalog release is created. A catalog release provides a snapshot of the product information taken at the time of publication. You can have one or more catalog releases available in your organization or in your store. If you publish a catalog for your organization, the catalog is available when the store is launched. If you have more than one catalog published for your store, use catalog rules to specify when to display each catalog. For example, you can use [**catalog rules**](/docs/api/pxm/catalog/rules) to schedule a catalog to appear during a particular date and time, such as a seasonal catalog. The catalog may have different pricing than the other catalogs. When a catalog is ready to be used in a store, you publish it. You can create and publish catalogs for different contexts and channels. Here are some pointers to understand a catalogs' lifecycle. - The default catalog is always the oldest published catalog and must have have at least one release. - At any time, the most recent three catalog releases are maintained. Hence, if there is a fourth catalog release, the first catalog release is automatically removed. - Until the catalog is published again, the previously created three catalog releases stay permanently. - If you want any other catalog to become the default catalog, you must create a catalog rule. - If you want the oldest published catalog to become the default catalog, you must remove the catalog rule. - Use the `sort_order` value in the `variations` to program your storefront to display the variation options in the order that you want. Here is a diagram that describes a catalogs' lifecycle: ![Catalogs' Lifecycle](/assets/catalog-lifecycle.png) ### Publishing catalogs When you publish a catalog, the `live` products in the hierarchies appear in a catalog release. A catalog release provides a snapshot of product information taken at the time of publication. You can have one or more catalog releases available in your organization or in your store. If you publish a catalog for your organization, the catalog is available when the store is launched. If you have more than one catalog published for your store, use catalog rules to specify when to display each catalog. For example, you can use [catalog rules](/docs/api/pxm/catalog/rules) to schedule a catalog to appear during a particular date and time, such as a seasonal catalog. The catalog may have different pricing than the other catalogs. You can have multiple published catalogs. When a catalog is ready to be used in a store, you publish it. You can create and publish catalogs for different contexts and channels. You can see the differences between the last two consecutive catalog releases. See [Publish a catalog](/docs/api/pxm/catalog/publish-release). You retrieve catalogs for your shopper experience by using the [Catalog View API](/docs/api/pxm/catalog/releases). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Rules If your store requires multiple catalogs, add catalog rules to control when a catalog is displayed. A catalog rule contains a catalog plus the criteria under which to display the catalog. :::caution You cannot create catalog rules for organization catalogs. ::: You can use catalog rules to schedule a catalog to appear during a particular period, such as on a specific date or during summer. The catalog might offer different pricing during this period. The pricing depends on the associated price book. The following scenarios provides a few examples for using catalog rules. - **Multiple geographical regions**. Display different catalogs in different regions with suitable pricing or combine product hierarchies from two different regions to display in a third region. - **Multiple channels**. Display different catalogs based on how a shopper accesses your store, such as through a mobile app or a web storefront. - **Direct to business versus direct to customers**. Offer different products and prices for business customers versus retail customers. - **Preferred accounts**. Offer special pricing to a group of users while displaying a standard price catalog to other users. - **Preferred customers**. Offer special pricing to preferred customers while displaying a standard price catalog to all other shoppers. - **Reward programs**. Enable reward programs where catalog prices drop after a certain spending level is reached. - **Product sales**. Offer sale items for a limited time. - **Standard pricing**. Display a default catalog to the shoppers who do not meet the criteria of the other catalog rules. You can define a catalog rule with any of the following criteria. - **Accounts**. List the accounts that should see a catalog. When a user has logged in with the account, they see the configured catalog. - **Customers**. List the customers that should see a catalog. When the customer is logged in, they see the configured catalog. - **Channel**. Specify a shopper experience, such as web storefront or mobile app. Set up the channel to retrieve the catalog from the catalog rule that matches that channel. - **Other tags**. Create your own user-defined tags. For example, you might want to tag by regions or you might want to distinguish between business and consumer customers. If a catalog rule has no criteria defined, it is the default catalog rule. ### Resolving catalog rules When there is a request for a catalog, the store displays the catalog with the rule that matches the most attributes of the shoppers context. The request triggers the following steps: 1. Compares the shoppers context against the defined catalog rules. 1. Determines the best match. 1. Retrieves the catalog associated with the matching catalog rule. The follow examples show how the best match might be resolved: - A shopper matches one of the `customer_ids` in one catalog rule only. The catalog for that catalog rule is displayed. - A shopper matches one of the `customer_ids` in one catalog rule only, but doesnʼt match any of the `tags` specified in that catalog rule. Because there are no other catalog rules for this `customer_id`, the catalog for the catalog rule is displayed because it is the best match. - A shopper is browsing a store using the stores mobile app, which matches `channel=mobile` in two catalog rules. The catalog displayed depends on matches with the `tags` or `customer_ids` attributes. If there is no other matching attribute, the first catalog rule found by the store is used. The best practice is to create catalog rules that cover all cases so that you avoid this situation. - An unknown shopper is browsing the only channel offered by the seller. The store displays the base catalog. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Shopper Catalog API Use the Shopper Catalog View API to retrieve hierarchy, node and product information for a catalog release. When you publish a catalog for a store, you can define catalog rules so that you can show catalogs with different pricing or different products to preferred customers or channels. These endpoints can be used in your customer-facing frontends. A catalog is a combination of one or more hierarchies, products, and a price book. Use the Products API and Hierarchies API to create a hierarchy of products that can be included in a catalog. Use the Price Book API to associate prices with products. ### Characteristics of Shopper Catalogs Shopper catalogs can have the following characteristics. - Use catalog rules to schedule a catalog to appear during a particular date and time, such as a seasonal catalog. The catalog may have different pricing than the other catalogs. You can have multiple published catalogs. - If you have defined catalog rules and you want to retrieve a published catalog for a particular channel or a user-defined tag, you must set the appropriate headers in the request: - `EP-Channel` - The channel, such as website or mobile app. See [**Create a Catalog Rule**](/docs/api/pxm/catalog/create-rule). - `EP-Context-Tag` - A tag defined in the store, such as `clearance`. See [**Create a Catalog Rule**](/docs/api/pxm/catalog/create-rule). * When a catalog is ready to be used in a store, you publish it. See [**Publish a Catalog**](/docs/api/pxm/catalog/publish-release). * You can create and publish catalogs for different contexts and channels. You can see the differences between the last 2 consecutive catalog releases. See [**Publish a Catalog**](/docs/api/pxm/catalog/publish-release). * You retrieve catalogs for your shopper experience by using the Shopper Catalog View API. For more information on how you can retrieve a catalog as a shopper using the Catalog API. * When a catalog is published for a store, the corresponding events contain `store_id` and `org_id`. * When a catalog is published for an organization, the corresponding events contain `org_id`. * Use the `sort_order` value in `variations` to program your storefront to display the variation options in the order that you want. ### Shopper Catalog Caching When conducting a `GET` on `catalog` endpoints, all data returned, including catalog releases, products, nodes and hierarchies, are cached for 5 minutes. This means, if you call the same endpoint again, the catalog data is retrieved from the cached objects pool, optimizing the performance and efficiency of your store front. If you use any of the `catalog` endpoints with a `filter` or `include` query parameter, these are cached separately. The cached entries disappear from the cached objects pool after 5 minutes. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Updates a catalog import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the catalog is not updated. Request --- ## Updates a catalog rule import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the catalog rule is not updated. Request --- ## Validate catalog rules for a given context import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Validates catalog rules for a given context and returns a list of matching catalog rules. Request --- ## Catalog Search Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Elastic Path Catalog Search provides fast, relevant product search capabilities for your published catalogs. Catalog Search enables shoppers to find products quickly using full-text search, filtering, faceting, and sorting, while giving merchandisers powerful tools to customize search relevance and ranking. You can integrate Catalog Search into your storefront using the Catalog Search API or manage search settings through Commerce Manager. ### How Catalog Search Works Catalog Search works alongside your Product Experience Manager catalogs to provide optimized search functionality. When creating or updating a catalog, enable search to allow the catalog's products to be indexed. See [Catalogs](/docs/api/pxm/catalog/catalogs). Then when a search-enabled catalog is published, the products are automatically indexed for search. The search index contains product data optimized for fast querying. Use the Search API to query products with full-text search, filtering, faceting, and sorting. The results of the search contain the full product information, not just the indexed fields, reducing the need for further API calls. ### Key Capabilities - **Full-text search**: Search across product names, descriptions, SKUs, and custom fields with typo tolerance and relevance ranking - **Filtering**: Narrow results using conditions on product attributes, categories, prices, and custom fields - **Faceting**: Get aggregated counts for attribute values to build dynamic navigation and refinement options - **Sorting**: Order results by price, name, custom fields, or relevance score - **Search Profiles**: Configure search behavior including field weights, filters, and boost rules without code changes - **Custom Fields**: Extend the search schema with your own product attributes for filtering, faceting, and sorting - **Fully Hydrated Responses**: Search results contain complete information about the products, reducing the requirement for follow-up API calls. ### Personalized Search Results Search results are automatically personalized based on the shopper's context. The system determines which catalog and prices to show based on: - **Channel**: The shopping experience, such as a web storefront or mobile app - **Account**: For B2B scenarios, the shopper's account and any parent accounts - **Customer**: The logged-in customer's segment or tier - **Tags**: Custom context tags for advanced segmentation scenarios See [**Characteristics of Shopper Catalogs**](/docs/api/pxm/catalog/shopper-catalog-api#characteristics-of-shopper-catalogs) for more information. ### Search Profiles Search Profiles give merchandisers control over search behavior without requiring code changes. With Search Profiles, you can: - **Configure field weights**: Control which product fields are most important for relevance ranking - **Apply default filters**: Enforce business rules like only showing live products - **Boost products**: Promote featured products, specific brands, or categories to the top of results - **A/B test**: Create multiple profiles to test different search configurations See [**Search Profiles**](/docs/api/pxm/catalog-search/search-profiles) for more information. ### Extending the Search Schema By default, the search index includes standard product fields like name, description, SKU, and categories. You can extend the schema by adding custom fields using [Indexable Fields](/docs/api/pxm/catalog-search/indexable-fields). Two types of custom fields can be indexed: - **Product extension fields** (`extensions.products().`): Fields from your product extension templates. - **Product custom attributes** (`shopper_attributes.` and `admin_attributes.`): Merchant-defined key/value attributes on products. This allows you to: - Search on custom product attributes like brand, material, or specifications - Filter products by custom fields like color, size, or rating - Display facets for custom field values in your navigation - Sort results by custom numeric fields like rating or popularity See [**Indexable Fields**](/docs/api/pxm/catalog-search/indexable-fields) for more information. Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Create indexable fields import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Specify additional fields to be indexed. Request ).` — indexes a field from a product extension template. The field must exist and be enabled in the flows service.\n- **Shopper attribute fields**: `shopper_attributes.` — indexes a merchant-defined shopper attribute. Always typed as `string`. The attribute name must be no longer than **64 characters** and can only contain alphanumeric characters, underscores (`_`), and hyphens (`-`).\n- **Admin attribute fields**: `admin_attributes.` — indexes a merchant-defined admin attribute. Always typed as `string`. The attribute name must be no longer than **64 characters** and can only contain alphanumeric characters, underscores (`_`), and hyphens (`-`).\n","example":"extensions.products(clothing).color","minLength":1},"facetable":{"type":"boolean","description":"Enables faceting on the field.","default":false,"example":true},"sortable":{"type":"boolean","description":"When set to true, the field will be sortable. Default: true for numbers, false otherwise.","example":true},"locale":{"type":"string","description":"For configuring language specific tokenization, e.g. jp for Japanese. Default: en which also broadly supports most European languages. For valid values, see [ISO 639 language codes](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes).","default":"en","example":"en"},"stem":{"type":"boolean","description":"When true, enables word stemming on this field using [Snowball stemmer](https://snowballstem.org/). Stemming reduces words to their root form at index and query time, so a search for \"running\" will also match products containing \"run\", \"runs\", or \"runner\". This improves search recall for descriptive text fields where shoppers may use different word forms than those used in product data. Only valid for string-typed fields. Defaults to false.\n","example":true,"title":"Stem"},"token_separators":{"type":"array","x-go-type-skip-optional-pointer":true,"items":{"type":"string","minLength":1,"maxLength":1},"description":"Per-field token separators for this field. Overrides the collection-level token_separators for this field. An empty array defers to the collection-level setting. Each element must be a single character.\nFor example, take text `non-tech`. By default, it will be tokenized to `nontech`. So, search for `non tech` will not match the product. Set `token_separators: [\"-\"]`. Then it will be tokenized to `non` and `tech`. Now, search for both `non-tech` and `non tech` will match this product.\n"},"symbols_to_index":{"type":"array","x-go-type-skip-optional-pointer":true,"items":{"type":"string","minLength":1,"maxLength":1},"description":"By default, special characters are removed from fields when indexing and searching for them. Provide per-field special characters to index for this field. Overrides the collection-level symbols_to_index for this field. An empty array defers to the collection-level setting. Each element must be a single character.\n"}},"title":"IndexableFieldRequest"},"example":[{"name":"extensions.products(clothing).color","facetable":false,"sortable":false,"locale":"en"},{"name":"shopper_attributes.fabric","facetable":false,"sortable":false},{"name":"admin_attributes.internal_grade","sortable":true}]},"core_field_overrides":{"type":"array","description":"Per-field configuration for core product fields (e.g. name, description).","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Name of the core field to configure. Must be one of the supported core fields.\n","example":"name"},"stem":{"type":"boolean","description":"When true, enables word stemming on this field using [Snowball stemmer](https://snowballstem.org/). Stemming reduces words to their root form at index and query time, so a search for \"running\" will also match products containing \"run\", \"runs\", or \"runner\". This improves search recall for descriptive text fields where shoppers may use different word forms than those used in product data. Only valid for string-typed fields. Defaults to false.\n","example":true,"title":"Stem"},"token_separators":{"type":"array","x-go-type-skip-optional-pointer":true,"items":{"type":"string","minLength":1,"maxLength":1},"description":"Per-field token separators for this core field. Overrides the collection-level token_separators for this field. An empty array defers to the collection-level setting. Each element must be a single character.\nFor example, take text `non-tech`. By default, it will be tokenized to `nontech`. So, search for `non tech` will not match the product. Set `token_separators: [\"-\"]`. Then it will be tokenized to `non` and `tech`. Now, search for both `non-tech` and `non tech` will match this product.\n"},"symbols_to_index":{"type":"array","x-go-type-skip-optional-pointer":true,"items":{"type":"string","minLength":1,"maxLength":1},"description":"By default, special characters are removed from fields when indexing and searching for them. Provide per-field special characters to index for this core field. Overrides the collection-level symbols_to_index for this field. An empty array defers to the collection-level setting. Each element must be a single character.\n"},"sortable":{"type":"boolean","description":"When set to true, enables sorting on this core field. Only supported for specific core fields.\n","example":true},"facetable":{"type":"boolean","description":"When set to true, enables faceting on this core field. A re-index is required for the change to take effect.\n","example":true}},"title":"CoreFieldOverride"}},"token_separators":{"type":"array","items":{"type":"string","minLength":1,"maxLength":1},"description":"Characters to use as token separators across all the index fields, in addition to spaces and newlines. Each element must be a single character. Defaults to none set.\nFor example, take text `non-tech`. By default, it will be tokenized to `nontech`. So, search for `non tech` will not match the product. Set `token_separators: [\"-\"]`. Then it will be tokenized to `non` and `tech`. Now, search for both `non-tech` and `non tech` will match this product.\n"},"symbols_to_index":{"type":"array","items":{"type":"string","minLength":1,"maxLength":1},"description":"By default, special characters are removed from fields when indexing and searching for them. Provide list of special characters that should be indexed as part of the tokens across the all index fields. Each element must be a single character. Defaults to none set.\n"}},"title":"IndexableFieldsRequestAttributes"}}}},"title":"IndexableFieldsCreateRequest"}}}}} > --- ## Create search profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a new search profile. Request Mens Shoes` && meta.display_price.without_tax.float_price:>100\").\nThese profile-level filters are ANDed with any filters provided in the search request via the filter_by parameter, resulting in: (profile_filter1 || profile_filter2 || ... profile_filterN) && request_filters.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"exclusions":{"type":"array","description":"A collection of exclusion expressions to apply to search results. Multiple exclusions in the array are combined using OR logic (records matching exclusion1 || exclusion2 || ... exclusionN).","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"boosts":{"type":"array","items":{"type":"object","description":"Defines a boosting rule that assigns a score to products matching a specific field value.","required":["condition","weight"],"properties":{"condition":{"type":"string","description":"A filter expression used to identify a subset of products for boosting. This follows the standard filter_by syntax.\n\nIt can be a simple condition like `meta.search.nodes.name:=\\`Electronics\\`` or complex like `meta.search.nodes.name:=\\`Electronics\\` && extensions.products(Details).brand:=Nike`.\n","minLength":1,"example":"meta.search.nodes.name:=\\`Electronics\\`"},"weight":{"type":"integer","description":"A numerical value representing the boost intensity. Products matching the criteria are assigned this value. Higher weights will cause products to appear earlier in the results.\n\n**Impact of Weights:**\n* **Boost (Positive):** Pushes products to the top.\n* **No affect (Zero):** Has no affect. Treated the same as products that match no rules.\n* **Bury (Negative):** Pushes products to the bottom.\n\n**Rule Evaluation:** The system uses \"Short-circuit\" evaluation. The engine stops at the **first matching rule**.\nThis means the weight of the first matching rule will be used as the product weight to sort the results.\nIf no rules match, the product is assigned a weight of `0`.\n","example":5}},"title":"SearchBoostRule"},"x-go-type-skip-optional-pointer":true},"prefix":{"type":"boolean","description":"Profile-level default for prefix (partial match) behavior on the last query token. When true, the last word in the query is treated as a prefix for all fields that do not have an explicit per-field prefix value. For example, a search request for \"red app\" matches \"red apple\". When false, the last word must match exactly. If omitted, default of true applies. Per-field prefix values override this setting.\nThe primary use case is to show results as the user is typing in the search box.\n","example":true},"typo_tolerance":{"type":"object","nullable":true,"description":"Optional typo tolerance configuration applied at search time.\nAll fields are optional; defaults are noted on each field.\n","properties":{"num_typos":{"type":"integer","description":"Profile-level default for the maximum number of typographical errors\n[Damerau-Levenshtein distance](https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance) allowed when matching any field.\nAccepted values: 0 (exact match only), 1, or 2.\nPer-field `num_typos` values override this setting. If omitted, default of 2 applies.\n\nFor example, a search request for \"red appla\" matches \"red apple\" with a `num_typos` of 1.\n\n**`num_typos` is an upper bound, not a guarantee.** The number of corrections actually\napplied to a query token is also capped by its length via\n`min_len_to_allow_single_character_correction` (default 4) and\n`min_len_to_allow_two_character_correction` (default 7): a token shorter than the\nsingle-character threshold gets no correction at all, and a token shorter than the\ntwo-character threshold is corrected by at most one character — even when `num_typos` is 2.\nSee those two fields for details.\n","minimum":0,"maximum":2,"example":1},"min_len_to_allow_single_character_correction":{"type":"integer","description":"Minimum query-token length required before a single-character typo correction is attempted. This works together with `num_typos`: a token shorter than this length receives no typo correction at all, regardless of `num_typos`. For example, when set to 4, a search for \"appla\" will match \"apple\", but a search for \"apa\" will not match \"app\" because the length of \"apa\" is 3.\nDefault: 4.\n","minimum":1,"example":3},"min_len_to_allow_two_character_correction":{"type":"integer","description":"Minimum query-token length required before a two-character typo correction is attempted. This works together with `num_typos`: even when `num_typos` is 2, a token shorter than this length is corrected by at most one character (and a token shorter than `min_len_to_allow_single_character_correction` is not corrected at all). For example, with the default of 7, the 7-character query \"monetar\" can be corrected to \"monitor\" (two corrections), but a 6-character query with two mistakes cannot.\nDefault: 7\n","minimum":1,"example":7},"typo_tokens_threshold":{"type":"integer","description":"Typo-corrected query variations are only generated if the number of exact results\nfound is fewer than this value. Set to 0 to disable typo tolerance entirely.\nFor example, when set to 5 and the search result only has 3 results, the search engine will apply typo correction to try to return 5 or more results.\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_threshold":{"type":"integer","description":"For multi-word queries, tokens are progressively dropped if the number of results\nis fewer than this value. Set to 0 to disable token dropping.\n\nFor example, when set to 5 and the search result only has 3 results for \"red apple\" search,\nthe search engine will drop the last token \"apple\" and find more results with just by searching for \"red\".\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_mode":{"type":"string","description":"Controls the direction in which tokens are dropped from a multi-word query when\nresults fall below drop_tokens_threshold.\n- `right_to_left` (default): drops tokens from the right end of the query first.\n- `left_to_right`: drops tokens from the left end first.\n- `both_sides:N`: drops from both ends, limited to queries of N tokens or fewer\n (e.g. `both_sides:3` applies only to queries with 3 or fewer tokens).\n","example":"right_to_left"},"enable_typos_for_numerical_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that are purely numeric (every character is a digit, e.g. \"98765\"). Such a token must then match exactly.\nDefault: true\n","example":true},"enable_typos_for_special_char_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that contain at least one non-alphanumeric character\n(any character outside `a-z`, `A-Z`, `0-9`), forcing such tokens to match exactly.\nUseful for keeping product codes / SKUs precise.\n\nTokens like `abc-123`, `abc-def`, `123-456`, and `v1.2.0` are affected;\na plain alphanumeric token like `abc123` is not.\n\nNote: the special character must be indexed on the field (via `symbols_to_index`);\notherwise the search engine removes the special characters from tokens\n(e.g. a token like v1.2.0 becomes v120) and it no longer qualifies.\n\nDefault: true\n","example":true},"split_join_tokens":{"type":"string","description":"Controls whether compound words and multi-word phrases are treated as equivalent during search.\nFor example, a query for \"nonstick\" may also match \"non stick\", and vice versa.\n- `fallback` (default): tries the original query form first; falls back to split/joined variants if results are insufficient.\n- `always`: always generates both split and joined token variants alongside the original query.\n- `off`: disables split/join token handling.\n","enum":["fallback","always","off"],"example":"fallback"}},"title":"TypoTolerance"},"synonym_settings":{"type":"object","nullable":true,"description":"Optional synonym tuning applied at search time. These settings control how synonym\nmatches are ranked and how query tokens are resolved against the synonym sets attached\nto the search profile. All fields are optional; defaults are noted on each field.\nThey only have an observable effect when synonym sets are attached to the resolved profile.\n","properties":{"demote_synonym_match":{"type":"boolean","description":"When true, results matched via a synonym are ranked below direct (non-synonym) matches. When false, synonym matches and direct matches are ranked equally.\nDefault: false\n","example":true},"synonym_resolution_allowed_on_prefix":{"type":"boolean","description":"When true, an incomplete (prefix) query token can resolve to a synonym, i.e. synonym\nexpansion is attempted on prefix tokens.\n\n**This is not the same as the `prefix` setting.** The `prefix` setting treats only the\n**last** word of the query as a prefix; `synonym_resolution_allowed_on_prefix` applies\nprefix matching at **every** token position when looking words up in the synonym sets —\nthere is no last-token special-casing.\n\n**Exact matches always win.** A query token that exactly equals a synonym key resolves\nregardless of this flag; the prefix behavior only affects the fuzzy fallback for tokens\nwith no exact synonym-key match. It composes with\n`number_of_typos_allowed_when_resolving_synonyms`, which governs typo tolerance during\nthe prefix/fuzzy lookup.\n\nWorked example (synonym keys `red`, `apple`, `apparel`):\n- `red app`: `red` matches exactly; `app` prefix-matches both `apple` and `apparel` — both expand.\n- `re app`: `re` prefix-matches `red` **and** `app` prefix-matches `apple`/`apparel` — both expand.\n The regular `prefix` setting would only treat the last word (`app`) as a prefix; here every\n position is prefix-matched.\n\nDefault: false\n","example":true},"number_of_typos_allowed_when_resolving_synonyms":{"type":"integer","description":"Number of typos allowed when resolving synonyms. Enables fuzzy synonym matching\nso that a misspelled query term can still trigger a synonym expansion for the\nsynonym sets attached to the search profile.\nAccepted values: 0 (exact synonym match only, default), 1, or 2.\n","minimum":0,"maximum":2,"example":0}},"title":"SynonymSettings"},"synonym_sets":{"type":"array","description":"Optional list of synonym set IDs to apply at search time. Each synonym set must exist and must have been synced to the search engine at least once. Organization-level search profiles may only reference organization-level synonym sets. Store-level search profiles may reference organization-level and same-store synonym sets.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","format":"uuid","example":"3fa85f64-5717-4562-b3fc-2c963f66afa6"}},"force_use_default_price_for_faceting_and_sorting":{"type":"boolean","description":"When set to true, the default price is used for faceting and sorting for segmented catalogs even if the catalog rule has a supported price book.","default":false,"example":true}},"title":"SearchProfileAttributes"}},"title":"SearchProfileCreateRequestData"}},"title":"SearchProfileCreateRequest"}}}}} > Mens Shoes` && meta.display_price.without_tax.float_price:>100\").\nThese profile-level filters are ANDed with any filters provided in the search request via the filter_by parameter, resulting in: (profile_filter1 || profile_filter2 || ... profile_filterN) && request_filters.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"exclusions":{"type":"array","description":"A collection of exclusion expressions to apply to search results. Multiple exclusions in the array are combined using OR logic (records matching exclusion1 || exclusion2 || ... exclusionN).","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"boosts":{"type":"array","items":{"type":"object","description":"Defines a boosting rule that assigns a score to products matching a specific field value.","required":["condition","weight"],"properties":{"condition":{"type":"string","description":"A filter expression used to identify a subset of products for boosting. This follows the standard filter_by syntax.\n\nIt can be a simple condition like `meta.search.nodes.name:=\\`Electronics\\`` or complex like `meta.search.nodes.name:=\\`Electronics\\` && extensions.products(Details).brand:=Nike`.\n","minLength":1,"example":"meta.search.nodes.name:=\\`Electronics\\`"},"weight":{"type":"integer","description":"A numerical value representing the boost intensity. Products matching the criteria are assigned this value. Higher weights will cause products to appear earlier in the results.\n\n**Impact of Weights:**\n* **Boost (Positive):** Pushes products to the top.\n* **No affect (Zero):** Has no affect. Treated the same as products that match no rules.\n* **Bury (Negative):** Pushes products to the bottom.\n\n**Rule Evaluation:** The system uses \"Short-circuit\" evaluation. The engine stops at the **first matching rule**.\nThis means the weight of the first matching rule will be used as the product weight to sort the results.\nIf no rules match, the product is assigned a weight of `0`.\n","example":5}},"title":"SearchBoostRule"},"x-go-type-skip-optional-pointer":true},"prefix":{"type":"boolean","description":"Profile-level default for prefix (partial match) behavior on the last query token. When true, the last word in the query is treated as a prefix for all fields that do not have an explicit per-field prefix value. For example, a search request for \"red app\" matches \"red apple\". When false, the last word must match exactly. If omitted, default of true applies. Per-field prefix values override this setting.\nThe primary use case is to show results as the user is typing in the search box.\n","example":true},"typo_tolerance":{"type":"object","nullable":true,"description":"Optional typo tolerance configuration applied at search time.\nAll fields are optional; defaults are noted on each field.\n","properties":{"num_typos":{"type":"integer","description":"Profile-level default for the maximum number of typographical errors\n[Damerau-Levenshtein distance](https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance) allowed when matching any field.\nAccepted values: 0 (exact match only), 1, or 2.\nPer-field `num_typos` values override this setting. If omitted, default of 2 applies.\n\nFor example, a search request for \"red appla\" matches \"red apple\" with a `num_typos` of 1.\n\n**`num_typos` is an upper bound, not a guarantee.** The number of corrections actually\napplied to a query token is also capped by its length via\n`min_len_to_allow_single_character_correction` (default 4) and\n`min_len_to_allow_two_character_correction` (default 7): a token shorter than the\nsingle-character threshold gets no correction at all, and a token shorter than the\ntwo-character threshold is corrected by at most one character — even when `num_typos` is 2.\nSee those two fields for details.\n","minimum":0,"maximum":2,"example":1},"min_len_to_allow_single_character_correction":{"type":"integer","description":"Minimum query-token length required before a single-character typo correction is attempted. This works together with `num_typos`: a token shorter than this length receives no typo correction at all, regardless of `num_typos`. For example, when set to 4, a search for \"appla\" will match \"apple\", but a search for \"apa\" will not match \"app\" because the length of \"apa\" is 3.\nDefault: 4.\n","minimum":1,"example":3},"min_len_to_allow_two_character_correction":{"type":"integer","description":"Minimum query-token length required before a two-character typo correction is attempted. This works together with `num_typos`: even when `num_typos` is 2, a token shorter than this length is corrected by at most one character (and a token shorter than `min_len_to_allow_single_character_correction` is not corrected at all). For example, with the default of 7, the 7-character query \"monetar\" can be corrected to \"monitor\" (two corrections), but a 6-character query with two mistakes cannot.\nDefault: 7\n","minimum":1,"example":7},"typo_tokens_threshold":{"type":"integer","description":"Typo-corrected query variations are only generated if the number of exact results\nfound is fewer than this value. Set to 0 to disable typo tolerance entirely.\nFor example, when set to 5 and the search result only has 3 results, the search engine will apply typo correction to try to return 5 or more results.\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_threshold":{"type":"integer","description":"For multi-word queries, tokens are progressively dropped if the number of results\nis fewer than this value. Set to 0 to disable token dropping.\n\nFor example, when set to 5 and the search result only has 3 results for \"red apple\" search,\nthe search engine will drop the last token \"apple\" and find more results with just by searching for \"red\".\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_mode":{"type":"string","description":"Controls the direction in which tokens are dropped from a multi-word query when\nresults fall below drop_tokens_threshold.\n- `right_to_left` (default): drops tokens from the right end of the query first.\n- `left_to_right`: drops tokens from the left end first.\n- `both_sides:N`: drops from both ends, limited to queries of N tokens or fewer\n (e.g. `both_sides:3` applies only to queries with 3 or fewer tokens).\n","example":"right_to_left"},"enable_typos_for_numerical_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that are purely numeric (every character is a digit, e.g. \"98765\"). Such a token must then match exactly.\nDefault: true\n","example":true},"enable_typos_for_special_char_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that contain at least one non-alphanumeric character\n(any character outside `a-z`, `A-Z`, `0-9`), forcing such tokens to match exactly.\nUseful for keeping product codes / SKUs precise.\n\nTokens like `abc-123`, `abc-def`, `123-456`, and `v1.2.0` are affected;\na plain alphanumeric token like `abc123` is not.\n\nNote: the special character must be indexed on the field (via `symbols_to_index`);\notherwise the search engine removes the special characters from tokens\n(e.g. a token like v1.2.0 becomes v120) and it no longer qualifies.\n\nDefault: true\n","example":true},"split_join_tokens":{"type":"string","description":"Controls whether compound words and multi-word phrases are treated as equivalent during search.\nFor example, a query for \"nonstick\" may also match \"non stick\", and vice versa.\n- `fallback` (default): tries the original query form first; falls back to split/joined variants if results are insufficient.\n- `always`: always generates both split and joined token variants alongside the original query.\n- `off`: disables split/join token handling.\n","enum":["fallback","always","off"],"example":"fallback"}},"title":"TypoTolerance"},"synonym_settings":{"type":"object","nullable":true,"description":"Optional synonym tuning applied at search time. These settings control how synonym\nmatches are ranked and how query tokens are resolved against the synonym sets attached\nto the search profile. All fields are optional; defaults are noted on each field.\nThey only have an observable effect when synonym sets are attached to the resolved profile.\n","properties":{"demote_synonym_match":{"type":"boolean","description":"When true, results matched via a synonym are ranked below direct (non-synonym) matches. When false, synonym matches and direct matches are ranked equally.\nDefault: false\n","example":true},"synonym_resolution_allowed_on_prefix":{"type":"boolean","description":"When true, an incomplete (prefix) query token can resolve to a synonym, i.e. synonym\nexpansion is attempted on prefix tokens.\n\n**This is not the same as the `prefix` setting.** The `prefix` setting treats only the\n**last** word of the query as a prefix; `synonym_resolution_allowed_on_prefix` applies\nprefix matching at **every** token position when looking words up in the synonym sets —\nthere is no last-token special-casing.\n\n**Exact matches always win.** A query token that exactly equals a synonym key resolves\nregardless of this flag; the prefix behavior only affects the fuzzy fallback for tokens\nwith no exact synonym-key match. It composes with\n`number_of_typos_allowed_when_resolving_synonyms`, which governs typo tolerance during\nthe prefix/fuzzy lookup.\n\nWorked example (synonym keys `red`, `apple`, `apparel`):\n- `red app`: `red` matches exactly; `app` prefix-matches both `apple` and `apparel` — both expand.\n- `re app`: `re` prefix-matches `red` **and** `app` prefix-matches `apple`/`apparel` — both expand.\n The regular `prefix` setting would only treat the last word (`app`) as a prefix; here every\n position is prefix-matched.\n\nDefault: false\n","example":true},"number_of_typos_allowed_when_resolving_synonyms":{"type":"integer","description":"Number of typos allowed when resolving synonyms. Enables fuzzy synonym matching\nso that a misspelled query term can still trigger a synonym expansion for the\nsynonym sets attached to the search profile.\nAccepted values: 0 (exact synonym match only, default), 1, or 2.\n","minimum":0,"maximum":2,"example":0}},"title":"SynonymSettings"},"synonym_sets":{"type":"array","description":"Optional list of synonym set IDs to apply at search time. Each synonym set must exist and must have been synced to the search engine at least once. Organization-level search profiles may only reference organization-level synonym sets. Store-level search profiles may reference organization-level and same-store synonym sets.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","format":"uuid","example":"3fa85f64-5717-4562-b3fc-2c963f66afa6"}},"force_use_default_price_for_faceting_and_sorting":{"type":"boolean","description":"When set to true, the default price is used for faceting and sorting for segmented catalogs even if the catalog rule has a supported price book.","default":false,"example":true}},"title":"SearchProfileAttributes"},"meta":{"type":"object","required":["default","owner"],"properties":{"default":{"type":"boolean","description":"Whether this is the default search profile.","example":true},"owner":{"description":"The resource owner, either `organization` or `store`.","type":"string","example":"organization","enum":["organization","store"],"x-go-type":"tenancy.Owner","x-go-type-import":{"path":"gitlab.elasticpath.com/commerce-cloud/ncl-projects/paragon/catalog-search.svc/internal/domain/tenancy"},"title":"ResourceOwner"}},"title":"SearchProfileMeta"}},"title":"SearchProfile"}},"title":"SearchProfileResponse"}}}},"400":{"description":"Bad request - invalid parameters","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"},"examples":{"internal-server-error":{"value":{"errors":[{"title":"Internal Server Error","status":"500"}]}}}}}}}} > --- ## Create stopword set import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a new stopwords set. Request --- ## Create synonym set import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a new synonym set. Request --- ## Delete indexable fields import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete additional fields to be indexed. Request --- ## Delete search profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a search profile. Request --- ## Delete stopword set import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a stopword set by ID. Request --- ## Delete synonym set import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a synonym set by ID. A synonym set cannot be deleted while it is being used by any search profile. Request --- ## Get indexable fields import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get additional fields to be indexed. Request --- ## Get search profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a search profile. Request Mens Shoes` && meta.display_price.without_tax.float_price:>100\").\nThese profile-level filters are ANDed with any filters provided in the search request via the filter_by parameter, resulting in: (profile_filter1 || profile_filter2 || ... profile_filterN) && request_filters.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"exclusions":{"type":"array","description":"A collection of exclusion expressions to apply to search results. Multiple exclusions in the array are combined using OR logic (records matching exclusion1 || exclusion2 || ... exclusionN).","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"boosts":{"type":"array","items":{"type":"object","description":"Defines a boosting rule that assigns a score to products matching a specific field value.","required":["condition","weight"],"properties":{"condition":{"type":"string","description":"A filter expression used to identify a subset of products for boosting. This follows the standard filter_by syntax.\n\nIt can be a simple condition like `meta.search.nodes.name:=\\`Electronics\\`` or complex like `meta.search.nodes.name:=\\`Electronics\\` && extensions.products(Details).brand:=Nike`.\n","minLength":1,"example":"meta.search.nodes.name:=\\`Electronics\\`"},"weight":{"type":"integer","description":"A numerical value representing the boost intensity. Products matching the criteria are assigned this value. Higher weights will cause products to appear earlier in the results.\n\n**Impact of Weights:**\n* **Boost (Positive):** Pushes products to the top.\n* **No affect (Zero):** Has no affect. Treated the same as products that match no rules.\n* **Bury (Negative):** Pushes products to the bottom.\n\n**Rule Evaluation:** The system uses \"Short-circuit\" evaluation. The engine stops at the **first matching rule**.\nThis means the weight of the first matching rule will be used as the product weight to sort the results.\nIf no rules match, the product is assigned a weight of `0`.\n","example":5}},"title":"SearchBoostRule"},"x-go-type-skip-optional-pointer":true},"prefix":{"type":"boolean","description":"Profile-level default for prefix (partial match) behavior on the last query token. When true, the last word in the query is treated as a prefix for all fields that do not have an explicit per-field prefix value. For example, a search request for \"red app\" matches \"red apple\". When false, the last word must match exactly. If omitted, default of true applies. Per-field prefix values override this setting.\nThe primary use case is to show results as the user is typing in the search box.\n","example":true},"typo_tolerance":{"type":"object","nullable":true,"description":"Optional typo tolerance configuration applied at search time.\nAll fields are optional; defaults are noted on each field.\n","properties":{"num_typos":{"type":"integer","description":"Profile-level default for the maximum number of typographical errors\n[Damerau-Levenshtein distance](https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance) allowed when matching any field.\nAccepted values: 0 (exact match only), 1, or 2.\nPer-field `num_typos` values override this setting. If omitted, default of 2 applies.\n\nFor example, a search request for \"red appla\" matches \"red apple\" with a `num_typos` of 1.\n\n**`num_typos` is an upper bound, not a guarantee.** The number of corrections actually\napplied to a query token is also capped by its length via\n`min_len_to_allow_single_character_correction` (default 4) and\n`min_len_to_allow_two_character_correction` (default 7): a token shorter than the\nsingle-character threshold gets no correction at all, and a token shorter than the\ntwo-character threshold is corrected by at most one character — even when `num_typos` is 2.\nSee those two fields for details.\n","minimum":0,"maximum":2,"example":1},"min_len_to_allow_single_character_correction":{"type":"integer","description":"Minimum query-token length required before a single-character typo correction is attempted. This works together with `num_typos`: a token shorter than this length receives no typo correction at all, regardless of `num_typos`. For example, when set to 4, a search for \"appla\" will match \"apple\", but a search for \"apa\" will not match \"app\" because the length of \"apa\" is 3.\nDefault: 4.\n","minimum":1,"example":3},"min_len_to_allow_two_character_correction":{"type":"integer","description":"Minimum query-token length required before a two-character typo correction is attempted. This works together with `num_typos`: even when `num_typos` is 2, a token shorter than this length is corrected by at most one character (and a token shorter than `min_len_to_allow_single_character_correction` is not corrected at all). For example, with the default of 7, the 7-character query \"monetar\" can be corrected to \"monitor\" (two corrections), but a 6-character query with two mistakes cannot.\nDefault: 7\n","minimum":1,"example":7},"typo_tokens_threshold":{"type":"integer","description":"Typo-corrected query variations are only generated if the number of exact results\nfound is fewer than this value. Set to 0 to disable typo tolerance entirely.\nFor example, when set to 5 and the search result only has 3 results, the search engine will apply typo correction to try to return 5 or more results.\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_threshold":{"type":"integer","description":"For multi-word queries, tokens are progressively dropped if the number of results\nis fewer than this value. Set to 0 to disable token dropping.\n\nFor example, when set to 5 and the search result only has 3 results for \"red apple\" search,\nthe search engine will drop the last token \"apple\" and find more results with just by searching for \"red\".\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_mode":{"type":"string","description":"Controls the direction in which tokens are dropped from a multi-word query when\nresults fall below drop_tokens_threshold.\n- `right_to_left` (default): drops tokens from the right end of the query first.\n- `left_to_right`: drops tokens from the left end first.\n- `both_sides:N`: drops from both ends, limited to queries of N tokens or fewer\n (e.g. `both_sides:3` applies only to queries with 3 or fewer tokens).\n","example":"right_to_left"},"enable_typos_for_numerical_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that are purely numeric (every character is a digit, e.g. \"98765\"). Such a token must then match exactly.\nDefault: true\n","example":true},"enable_typos_for_special_char_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that contain at least one non-alphanumeric character\n(any character outside `a-z`, `A-Z`, `0-9`), forcing such tokens to match exactly.\nUseful for keeping product codes / SKUs precise.\n\nTokens like `abc-123`, `abc-def`, `123-456`, and `v1.2.0` are affected;\na plain alphanumeric token like `abc123` is not.\n\nNote: the special character must be indexed on the field (via `symbols_to_index`);\notherwise the search engine removes the special characters from tokens\n(e.g. a token like v1.2.0 becomes v120) and it no longer qualifies.\n\nDefault: true\n","example":true},"split_join_tokens":{"type":"string","description":"Controls whether compound words and multi-word phrases are treated as equivalent during search.\nFor example, a query for \"nonstick\" may also match \"non stick\", and vice versa.\n- `fallback` (default): tries the original query form first; falls back to split/joined variants if results are insufficient.\n- `always`: always generates both split and joined token variants alongside the original query.\n- `off`: disables split/join token handling.\n","enum":["fallback","always","off"],"example":"fallback"}},"title":"TypoTolerance"},"synonym_settings":{"type":"object","nullable":true,"description":"Optional synonym tuning applied at search time. These settings control how synonym\nmatches are ranked and how query tokens are resolved against the synonym sets attached\nto the search profile. All fields are optional; defaults are noted on each field.\nThey only have an observable effect when synonym sets are attached to the resolved profile.\n","properties":{"demote_synonym_match":{"type":"boolean","description":"When true, results matched via a synonym are ranked below direct (non-synonym) matches. When false, synonym matches and direct matches are ranked equally.\nDefault: false\n","example":true},"synonym_resolution_allowed_on_prefix":{"type":"boolean","description":"When true, an incomplete (prefix) query token can resolve to a synonym, i.e. synonym\nexpansion is attempted on prefix tokens.\n\n**This is not the same as the `prefix` setting.** The `prefix` setting treats only the\n**last** word of the query as a prefix; `synonym_resolution_allowed_on_prefix` applies\nprefix matching at **every** token position when looking words up in the synonym sets —\nthere is no last-token special-casing.\n\n**Exact matches always win.** A query token that exactly equals a synonym key resolves\nregardless of this flag; the prefix behavior only affects the fuzzy fallback for tokens\nwith no exact synonym-key match. It composes with\n`number_of_typos_allowed_when_resolving_synonyms`, which governs typo tolerance during\nthe prefix/fuzzy lookup.\n\nWorked example (synonym keys `red`, `apple`, `apparel`):\n- `red app`: `red` matches exactly; `app` prefix-matches both `apple` and `apparel` — both expand.\n- `re app`: `re` prefix-matches `red` **and** `app` prefix-matches `apple`/`apparel` — both expand.\n The regular `prefix` setting would only treat the last word (`app`) as a prefix; here every\n position is prefix-matched.\n\nDefault: false\n","example":true},"number_of_typos_allowed_when_resolving_synonyms":{"type":"integer","description":"Number of typos allowed when resolving synonyms. Enables fuzzy synonym matching\nso that a misspelled query term can still trigger a synonym expansion for the\nsynonym sets attached to the search profile.\nAccepted values: 0 (exact synonym match only, default), 1, or 2.\n","minimum":0,"maximum":2,"example":0}},"title":"SynonymSettings"},"synonym_sets":{"type":"array","description":"Optional list of synonym set IDs to apply at search time. Each synonym set must exist and must have been synced to the search engine at least once. Organization-level search profiles may only reference organization-level synonym sets. Store-level search profiles may reference organization-level and same-store synonym sets.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","format":"uuid","example":"3fa85f64-5717-4562-b3fc-2c963f66afa6"}},"force_use_default_price_for_faceting_and_sorting":{"type":"boolean","description":"When set to true, the default price is used for faceting and sorting for segmented catalogs even if the catalog rule has a supported price book.","default":false,"example":true}},"title":"SearchProfileAttributes"},"meta":{"type":"object","required":["default","owner"],"properties":{"default":{"type":"boolean","description":"Whether this is the default search profile.","example":true},"owner":{"description":"The resource owner, either `organization` or `store`.","type":"string","example":"organization","enum":["organization","store"],"x-go-type":"tenancy.Owner","x-go-type-import":{"path":"gitlab.elasticpath.com/commerce-cloud/ncl-projects/paragon/catalog-search.svc/internal/domain/tenancy"},"title":"ResourceOwner"}},"title":"SearchProfileMeta"}},"title":"SearchProfile"}},"title":"SearchProfileResponse"}}}},"400":{"description":"Bad request - invalid parameters","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"}}}},"404":{"description":"Search profile not found","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"},"examples":{"internal-server-error":{"value":{"errors":[{"title":"Internal Server Error","status":"500"}]}}}}}}}} > --- ## Get stopword set import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a stopwords set by ID. Request --- ## Get synonym set import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a synonym set by ID. Request --- ## Indexable Fields Indexable Fields allow you to extend and fine-tune the search schema. By default, the search index includes all the core product fields like name, description, SKU, slug etc. Indexable Fields let you: - **Add custom fields** to the index from product extension templates or custom (shopper and admin) attributes - **Configure core field behavior** such as stemming and tokenization on built-in fields like `name` and `description` - **Control tokenization** at the collection or per-field level using token separators and symbols to index ### When to Use Indexable Fields Use Indexable Fields when you want to: - **Search custom attributes**: Enable full-text search on custom product fields like brand, material, or specifications - **Filter by custom attributes**: Allow shoppers to filter products by custom fields like color, size, or rating - **Facet on custom attributes**: Display aggregated counts for custom field values in your navigation - **Sort by custom attributes**: Order search results by custom numeric fields like rating or popularity - **Enable stemming**: Match different word forms (e.g., "running" also matches "run", "runs") on both custom or core fields - **Customize tokenization**: Control how hyphenated, compound, or symbol-containing text is split and indexed ### How Indexable Fields Work 1. **Create indexable fields**: Define custom fields to index and configure collection-level or per-field tokenization settings 2. **Override core field behavior**: Use `core_field_overrides` to configure stemming, token separators, or symbols to index on built-in fields like `name` and `description` 3. **Reindex catalogs**: After creating or modifying indexable fields, reindex your catalog releases to apply the changes 4. **Use in searches**: Once reindexed, custom fields are available in search queries for filtering, faceting, and sorting ### Field Configuration Each entry in the custom fields (`fields` array) supports the following options: | Option | Description | |--------------------|-----------------------------------------------------------------------------------------------------------| | `name` | The field path — see **Field Types** below for supported formats | | `facetable` | When `true`, the field can be used for faceting to show aggregated value counts | | `sortable` | When `true`, the field can be used for sorting results | | `locale` | Language code for text tokenization, defaults to `en` for English | | `stem` | When `true`, enables word stemming using the Snowball stemmer — see **Stemming** below | | `token_separators` | Per-field characters to use as token separators, overriding the collection-level setting | | `symbols_to_index` | Per-field special characters to preserve as part of tokens, overriding the collection-level setting | ### Field Types Two categories of fields can be indexed: #### Extension Fields Fields from your product extension templates, following the pattern `extensions.products().`: - `` is the slug of your product extension template - `` is the name of the field within that template - The field must exist and be enabled in the flows service - Only enumerated string fields, numeric fields, and boolean fields can be faceted **Example**: For a product extension template with slug `Details` containing a field `brand`, the indexable field name would be `extensions.products(Details).brand`. #### Custom Attribute Fields Merchant-defined key/value attributes stored directly on products: - `shopper_attributes.` — visible in shopper and admin catalog API responses and available for filtering, sorting, and faceting in both shopper and admin search - `admin_attributes.` — available for filtering and sorting in both shopper and admin search; not returned in search response payloads - `` must be no longer than **64 characters** and can only contain alphanumeric characters, underscores (`_`), and hyphens (`-`). - Attribute fields are always typed as `string` - Faceting and sorting can be enabled **Examples**: `shopper_attributes.fabric`, `admin_attributes.internal_grade` ### Core Field Overrides In addition to configuring custom fields, Indexable Fields can influence the behavior of built-in product fields such as `name`, `description`, and `sku`. Use the `core_field_overrides` to apply per-field settings. Each entry in `core_field_overrides` supports `stem`, `token_separators`, `symbols_to_index`, `sortable`, and `facetable`. This is useful when you want to enable stemming on the product description, apply custom tokenization to a specific core field, or enable sorting on fields like `name` and `sku`. **Example**: Enable stemming on `description` and treat hyphens as token separators only on `name`: ```json { "core_field_overrides": [ { "name": "description", "stem": true }, { "name": "name", "token_separators": ["-"], "sortable": true } ] } ``` ### Stemming Stemming reduces words to their root form at both index and query time, so a search for "running" also matches products containing "run", "runs", or "runner". This improves search recall for descriptive text fields where shoppers may use different word forms than those found in product data. - Enable per field using `stem: true` on any entry in `fields` or `core_field_overrides` - Uses the [Snowball stemmer](https://snowballstem.org/) - Only valid for string-typed fields - Defaults to `false` ### Token Separators and Symbols to Index These settings control how text is split into tokens during indexing and searching. #### Token Separators `token_separators` specifies characters that split text into separate tokens, in addition to the default whitespace splitting. This is useful for hyphenated text, part numbers, or other compound formats. For example, with `token_separators: ["-"]`, the text `non-tech` is tokenized to `non` and `tech`, so searches for both `non-tech` and `non tech` will match. #### Symbols to Index `symbols_to_index` specifies special characters that should be preserved within tokens rather than stripped during indexing. Useful when products contain meaningful symbols like `+`, `#`, or `@`. #### Collection-Level vs Field-Level Both settings can be configured at two scopes: - **Collection-level**: Set `token_separators` or `symbols_to_index` at the top level of the indexable fields resource to apply the setting across all indexed fields. - **Field-level**: Set the same properties on an individual entry in `fields` or `core_field_overrides` to apply only to that field, overriding the collection-level setting. An empty array at the field level defers to the collection-level setting. ### Reindexing Requirement Any change to indexable fields requires reindexing your catalog releases to take effect. The system detects when indexes are out of sync. Use the [reindex endpoint](/docs/api/pxm/catalog-search/reindex-tenant-releases) to apply changes. See [Jobs](/docs/api/pxm/catalog-search/jobs) for more details on reindexing operations. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Jobs(Catalog-search) Jobs manage the indexing operations for catalog search. When catalogs are published or when reindexing is required, jobs process the product data and build search indexes. ### Job Types | Type | Description | |---------------------------|-----------------------------------------------------------------------------------------------------| | `index-release` | Index a specific catalog release. Created automatically when a search-enabled catalog is published. | | `delete-release` | Remove the search index for a catalog release. | | `reindex-tenant-releases` | Reindex all catalog releases for the store. Use when indexable fields have changed. | ### Job Lifecycle Jobs progress through the following states: 1. **pending**: Job has been created and is waiting to be processed 2. **processing**: Job is actively indexing products 3. **complete**: Job finished successfully 4. **failed**: Job encountered an error ### Automatic Indexing When you publish a catalog with search enabled, an `index-release` job is automatically created. The catalog release remains in a publishing state until the indexing job completes successfully. ### Manual Reindexing Use the reindex endpoint when: - You've added, modified, or deleted indexable fields - Search indexes are out of sync (check via [Search Indexes](/docs/api/pxm/catalog-search/search-indexes)) - You need to rebuild indexes after a failure The reindex operation creates jobs for all catalog releases that need updating. You can optionally force a full reindex of all releases regardless of their sync status. ### Conflict Handling Only one reindexing operation can run at a time. If you attempt to start a reindex while another is in progress, the API returns a 409 Conflict error. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## List indexable fields import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List indexable fields. --- ## List search indexes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List search indexes. Request --- ## List search profiles import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List search profiles. Mens Shoes` && meta.display_price.without_tax.float_price:>100\").\nThese profile-level filters are ANDed with any filters provided in the search request via the filter_by parameter, resulting in: (profile_filter1 || profile_filter2 || ... profile_filterN) && request_filters.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"exclusions":{"type":"array","description":"A collection of exclusion expressions to apply to search results. Multiple exclusions in the array are combined using OR logic (records matching exclusion1 || exclusion2 || ... exclusionN).","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"boosts":{"type":"array","items":{"type":"object","description":"Defines a boosting rule that assigns a score to products matching a specific field value.","required":["condition","weight"],"properties":{"condition":{"type":"string","description":"A filter expression used to identify a subset of products for boosting. This follows the standard filter_by syntax.\n\nIt can be a simple condition like `meta.search.nodes.name:=\\`Electronics\\`` or complex like `meta.search.nodes.name:=\\`Electronics\\` && extensions.products(Details).brand:=Nike`.\n","minLength":1,"example":"meta.search.nodes.name:=\\`Electronics\\`"},"weight":{"type":"integer","description":"A numerical value representing the boost intensity. Products matching the criteria are assigned this value. Higher weights will cause products to appear earlier in the results.\n\n**Impact of Weights:**\n* **Boost (Positive):** Pushes products to the top.\n* **No affect (Zero):** Has no affect. Treated the same as products that match no rules.\n* **Bury (Negative):** Pushes products to the bottom.\n\n**Rule Evaluation:** The system uses \"Short-circuit\" evaluation. The engine stops at the **first matching rule**.\nThis means the weight of the first matching rule will be used as the product weight to sort the results.\nIf no rules match, the product is assigned a weight of `0`.\n","example":5}},"title":"SearchBoostRule"},"x-go-type-skip-optional-pointer":true},"prefix":{"type":"boolean","description":"Profile-level default for prefix (partial match) behavior on the last query token. When true, the last word in the query is treated as a prefix for all fields that do not have an explicit per-field prefix value. For example, a search request for \"red app\" matches \"red apple\". When false, the last word must match exactly. If omitted, default of true applies. Per-field prefix values override this setting.\nThe primary use case is to show results as the user is typing in the search box.\n","example":true},"typo_tolerance":{"type":"object","nullable":true,"description":"Optional typo tolerance configuration applied at search time.\nAll fields are optional; defaults are noted on each field.\n","properties":{"num_typos":{"type":"integer","description":"Profile-level default for the maximum number of typographical errors\n[Damerau-Levenshtein distance](https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance) allowed when matching any field.\nAccepted values: 0 (exact match only), 1, or 2.\nPer-field `num_typos` values override this setting. If omitted, default of 2 applies.\n\nFor example, a search request for \"red appla\" matches \"red apple\" with a `num_typos` of 1.\n\n**`num_typos` is an upper bound, not a guarantee.** The number of corrections actually\napplied to a query token is also capped by its length via\n`min_len_to_allow_single_character_correction` (default 4) and\n`min_len_to_allow_two_character_correction` (default 7): a token shorter than the\nsingle-character threshold gets no correction at all, and a token shorter than the\ntwo-character threshold is corrected by at most one character — even when `num_typos` is 2.\nSee those two fields for details.\n","minimum":0,"maximum":2,"example":1},"min_len_to_allow_single_character_correction":{"type":"integer","description":"Minimum query-token length required before a single-character typo correction is attempted. This works together with `num_typos`: a token shorter than this length receives no typo correction at all, regardless of `num_typos`. For example, when set to 4, a search for \"appla\" will match \"apple\", but a search for \"apa\" will not match \"app\" because the length of \"apa\" is 3.\nDefault: 4.\n","minimum":1,"example":3},"min_len_to_allow_two_character_correction":{"type":"integer","description":"Minimum query-token length required before a two-character typo correction is attempted. This works together with `num_typos`: even when `num_typos` is 2, a token shorter than this length is corrected by at most one character (and a token shorter than `min_len_to_allow_single_character_correction` is not corrected at all). For example, with the default of 7, the 7-character query \"monetar\" can be corrected to \"monitor\" (two corrections), but a 6-character query with two mistakes cannot.\nDefault: 7\n","minimum":1,"example":7},"typo_tokens_threshold":{"type":"integer","description":"Typo-corrected query variations are only generated if the number of exact results\nfound is fewer than this value. Set to 0 to disable typo tolerance entirely.\nFor example, when set to 5 and the search result only has 3 results, the search engine will apply typo correction to try to return 5 or more results.\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_threshold":{"type":"integer","description":"For multi-word queries, tokens are progressively dropped if the number of results\nis fewer than this value. Set to 0 to disable token dropping.\n\nFor example, when set to 5 and the search result only has 3 results for \"red apple\" search,\nthe search engine will drop the last token \"apple\" and find more results with just by searching for \"red\".\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_mode":{"type":"string","description":"Controls the direction in which tokens are dropped from a multi-word query when\nresults fall below drop_tokens_threshold.\n- `right_to_left` (default): drops tokens from the right end of the query first.\n- `left_to_right`: drops tokens from the left end first.\n- `both_sides:N`: drops from both ends, limited to queries of N tokens or fewer\n (e.g. `both_sides:3` applies only to queries with 3 or fewer tokens).\n","example":"right_to_left"},"enable_typos_for_numerical_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that are purely numeric (every character is a digit, e.g. \"98765\"). Such a token must then match exactly.\nDefault: true\n","example":true},"enable_typos_for_special_char_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that contain at least one non-alphanumeric character\n(any character outside `a-z`, `A-Z`, `0-9`), forcing such tokens to match exactly.\nUseful for keeping product codes / SKUs precise.\n\nTokens like `abc-123`, `abc-def`, `123-456`, and `v1.2.0` are affected;\na plain alphanumeric token like `abc123` is not.\n\nNote: the special character must be indexed on the field (via `symbols_to_index`);\notherwise the search engine removes the special characters from tokens\n(e.g. a token like v1.2.0 becomes v120) and it no longer qualifies.\n\nDefault: true\n","example":true},"split_join_tokens":{"type":"string","description":"Controls whether compound words and multi-word phrases are treated as equivalent during search.\nFor example, a query for \"nonstick\" may also match \"non stick\", and vice versa.\n- `fallback` (default): tries the original query form first; falls back to split/joined variants if results are insufficient.\n- `always`: always generates both split and joined token variants alongside the original query.\n- `off`: disables split/join token handling.\n","enum":["fallback","always","off"],"example":"fallback"}},"title":"TypoTolerance"},"synonym_settings":{"type":"object","nullable":true,"description":"Optional synonym tuning applied at search time. These settings control how synonym\nmatches are ranked and how query tokens are resolved against the synonym sets attached\nto the search profile. All fields are optional; defaults are noted on each field.\nThey only have an observable effect when synonym sets are attached to the resolved profile.\n","properties":{"demote_synonym_match":{"type":"boolean","description":"When true, results matched via a synonym are ranked below direct (non-synonym) matches. When false, synonym matches and direct matches are ranked equally.\nDefault: false\n","example":true},"synonym_resolution_allowed_on_prefix":{"type":"boolean","description":"When true, an incomplete (prefix) query token can resolve to a synonym, i.e. synonym\nexpansion is attempted on prefix tokens.\n\n**This is not the same as the `prefix` setting.** The `prefix` setting treats only the\n**last** word of the query as a prefix; `synonym_resolution_allowed_on_prefix` applies\nprefix matching at **every** token position when looking words up in the synonym sets —\nthere is no last-token special-casing.\n\n**Exact matches always win.** A query token that exactly equals a synonym key resolves\nregardless of this flag; the prefix behavior only affects the fuzzy fallback for tokens\nwith no exact synonym-key match. It composes with\n`number_of_typos_allowed_when_resolving_synonyms`, which governs typo tolerance during\nthe prefix/fuzzy lookup.\n\nWorked example (synonym keys `red`, `apple`, `apparel`):\n- `red app`: `red` matches exactly; `app` prefix-matches both `apple` and `apparel` — both expand.\n- `re app`: `re` prefix-matches `red` **and** `app` prefix-matches `apple`/`apparel` — both expand.\n The regular `prefix` setting would only treat the last word (`app`) as a prefix; here every\n position is prefix-matched.\n\nDefault: false\n","example":true},"number_of_typos_allowed_when_resolving_synonyms":{"type":"integer","description":"Number of typos allowed when resolving synonyms. Enables fuzzy synonym matching\nso that a misspelled query term can still trigger a synonym expansion for the\nsynonym sets attached to the search profile.\nAccepted values: 0 (exact synonym match only, default), 1, or 2.\n","minimum":0,"maximum":2,"example":0}},"title":"SynonymSettings"},"synonym_sets":{"type":"array","description":"Optional list of synonym set IDs to apply at search time. Each synonym set must exist and must have been synced to the search engine at least once. Organization-level search profiles may only reference organization-level synonym sets. Store-level search profiles may reference organization-level and same-store synonym sets.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","format":"uuid","example":"3fa85f64-5717-4562-b3fc-2c963f66afa6"}},"force_use_default_price_for_faceting_and_sorting":{"type":"boolean","description":"When set to true, the default price is used for faceting and sorting for segmented catalogs even if the catalog rule has a supported price book.","default":false,"example":true}},"title":"SearchProfileAttributes"},"meta":{"type":"object","required":["default","owner"],"properties":{"default":{"type":"boolean","description":"Whether this is the default search profile.","example":true},"owner":{"description":"The resource owner, either `organization` or `store`.","type":"string","example":"organization","enum":["organization","store"],"x-go-type":"tenancy.Owner","x-go-type-import":{"path":"gitlab.elasticpath.com/commerce-cloud/ncl-projects/paragon/catalog-search.svc/internal/domain/tenancy"},"title":"ResourceOwner"}},"title":"SearchProfileMeta"}},"title":"SearchProfile"}},"meta":{"type":"object","required":["results"],"properties":{"results":{"description":"Contains the results for the entire collection.","type":"object","required":["total"],"properties":{"total":{"description":"Total number of results for the entire collection.","type":"integer","example":100}},"title":"ListResponseMetaResults"}},"title":"ListResponseMeta"}},"title":"ListSearchProfilesResponse"}}}},"400":{"description":"Bad request - invalid parameters","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"},"examples":{"internal-server-error":{"value":{"errors":[{"title":"Internal Server Error","status":"500"}]}}}}}}}} > --- ## List searchable fields import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List searchable fields. --- ## List stopword sets import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List all stopwords sets. --- ## List synonym sets import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List all synonym sets. --- ## Admin Multi-search import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Execute one or more searches in a single request. Request =10.00","title":"FilterByField"},"sort_by":{"type":"string","description":"Orders search results by specified fields. See [sorting](/guides/How-To/Catalogs/Search/sorting) for more details.","example":"price.amount:asc,extensions.products(Specification).rating:desc","title":"SortByField"},"max_facet_values":{"type":"integer","example":10},"page":{"type":"integer","example":1},"per_page":{"type":"integer","example":20}},"title":"SearchQuery"}}},"title":"MultiSearchRequest"}}}}} > --- ## Multi-search import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Execute one or more searches in a single request. Request =10.00","title":"FilterByField"},"sort_by":{"type":"string","description":"Orders search results by specified fields. See [sorting](/guides/How-To/Catalogs/Search/sorting) for more details.","example":"price.amount:asc,extensions.products(Specification).rating:desc","title":"SortByField"},"max_facet_values":{"type":"integer","example":10},"page":{"type":"integer","example":1},"per_page":{"type":"integer","example":20}},"title":"SearchQuery"}}},"title":"MultiSearchRequest"}}}}} > --- ## Reindex all releases for tenant import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a new job to reindex all releases for the tenant. Request --- ## Admin Search import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Execute search. Request =10.00","schema":{"type":"string"}},{"in":"query","name":"sort_by","description":"Orders search results by specified fields. See [sorting](/guides/How-To/Catalogs/Search/sorting) for more details.","example":"price.amount:asc,extensions.products(Specification).rating:desc","schema":{"type":"string"}},{"in":"query","name":"max_facet_values","description":"Maximum number of facet values to return","schema":{"type":"integer"},"example":10},{"in":"header","name":"EP-Simulated-Shopper-Date","schema":{"type":"string"},"required":false},{"in":"query","name":"page","schema":{"type":"integer"},"example":1},{"in":"query","name":"per_page","schema":{"type":"integer"},"example":10}]} > --- ## Search import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Execute search. Request =10.00","schema":{"type":"string"}},{"in":"query","name":"sort_by","description":"Orders search results by specified fields. See [sorting](/guides/How-To/Catalogs/Search/sorting) for more details.","example":"price.amount:asc,extensions.products(Specification).rating:desc","schema":{"type":"string"}},{"in":"query","name":"max_facet_values","description":"Maximum number of facet values to return","schema":{"type":"integer"},"example":10},{"in":"header","name":"EP-Simulated-Shopper-Date","schema":{"type":"string"},"required":false},{"in":"query","name":"page","schema":{"type":"integer"},"example":1},{"in":"query","name":"per_page","schema":{"type":"integer"},"example":10}]} > --- ## Search Indexes Search Indexes represent the indexed data for your catalog releases. Each time a catalog is published with search enabled, a search index is created containing the product data optimized for fast querying. ### Index Status The Search Indexes API allows you to view the status of your indexes and identify any that are out of sync. An index becomes out of sync when: - Indexable fields have been added, modified, or deleted - The index failed to build during catalog publishing - A reindex is required due to schema changes ### Monitoring Indexes Use the list endpoint to: - **View all indexes**: See all search indexes for your store - **Check sync status**: Identify indexes that need reindexing - **Filter by status**: Find only out-of-sync indexes using the `out_of_sync` query parameter ### Index Information Each search index includes: | Property | Description | |---------------|---------------------------------------------------------| | `catalog_id` | The ID of the catalog this index belongs to | | `release_id` | The ID of the catalog release this index was built from | | `out_of_sync` | Whether the index needs to be rebuilt | ### Reindexing When indexes are out of sync, use the reindex endpoint in [Jobs](/docs/api/pxm/catalog-search/jobs) to rebuild them. Reindexing ensures your search indexes reflect the current indexable field configuration. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Search Profiles Search Profiles are configuration objects that control how search queries are executed. They provide a powerful way to customize search relevance, filtering, and ranking without requiring code changes, enabling merchandisers and business users to optimize the search experience. ### How Search Profiles Work A Search Profile defines: - **Which fields to search**: Select which product fields are included in search queries - **Field weights**: Assign relative importance to each field for relevance ranking - **Default filters**: Apply business rules that filter results for all searches - **Boost rules**: Promote or demote products based on specific conditions - **Match type**: Control how scores from multiple fields are combined When a search request is made, the system uses the specified profile (or the default profile) to configure the search behavior. ### Search Profile Components | Component | Description | |-------------------|-------------------------------------------------------------------------------------------| | `slug` | Unique identifier used to reference the profile in search requests | | `fields` | List of fields to search with optional weights for relevance ranking | | `filters` | Default filter expressions applied to all searches using this profile | | `boosts` | Rules for promoting or demoting products based on conditions | | `text_match_type` | How to combine scores when multiple fields match (`max_score`, `max_weight`, `sum_score`) | ### Field Weights Field weights control how important each field is when ranking search results. Higher weights mean matches in that field contribute more to the relevance score. Weights must be in the range `[0, 15]`. **Example**: A profile with `name` (weight 10) and `description` (weight 5) will rank products with search term matches in the name higher than those with matches only in the description. ### Filters Profile filters enforce business rules that apply to all searches: - Ensure only live/published products appear in results - Restrict results to specific categories or channels - Hide products based on visibility settings Multiple filters are combined with OR logic, then ANDed with any filters in the search request. ### Boost Rules Boost rules allow you to promote or demote products in search results: - **Positive weights**: Push matching products to the top of results - **Negative weights**: Push matching products to the bottom (burying) - **Zero weight**: No effect on ranking Rules are evaluated in weight order, and the first matching rule determines the product's boost. ### Text Match Types | Type | Description | |--------------|----------------------------------------------------------------------------------------| | `max_score` | Uses the highest score from any single matching field. Prioritizes match quality. | | `max_weight` | Uses the score from the highest-weighted matching field. Prioritizes field importance. | | `sum_score` | Sums weighted scores from all matching fields. Rewards multi-field matches. | ### Default Profile Each store has a default search profile that is used when no profile is specified in the search request. You can set any profile as the default using the set default endpoint. ### Use Cases - **A/B testing**: Create multiple profiles with different configurations to test search relevance - **Channel optimization**: Different profiles for web, mobile, and B2B channels - **Seasonal merchandising**: Profiles that boost seasonal or promotional products - **Customer segmentation**: Different ranking strategies for different customer tiers ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Search(Catalog-search) The Search API enables you to search for products in your published catalogs. Search provides powerful capabilities including full-text search, filtering, faceting, and sorting to help shoppers find products quickly and efficiently. ### How Search Works When you publish a catalog with search enabled, the catalog's products are automatically indexed for search. The search index contains product data optimized for fast querying, including product names, descriptions, SKUs, categories, prices, and any custom fields you've configured. There are two types of search operations: - **Search**: Execute a single search query against a catalog. Use the GET endpoint for simple searches with query parameters. - **Multi-search**: Execute multiple search queries in a single request. Use the POST endpoint to batch searches together for improved performance. ### Search Features - **Full-text search**: Search across product names, descriptions, SKUs, and custom fields with typo tolerance and relevance ranking - **Filtering**: Narrow results using conditions on product attributes, categories, prices, and custom fields - **Faceting**: Get aggregated counts for attribute values to build dynamic navigation and refinement options - **Sorting**: Order results by price, name, custom fields, or relevance score - **Highlighting**: Get highlighted snippets showing where search terms match in product fields - **Autocomplete**: Get search suggestions as shoppers type their queries ### Shopper Context Search results are personalized based on the shopper's context. The system automatically determines which catalog and prices to use based on: - **Channel**: The shopping experience (web, mobile, B2B portal) - **Account**: For B2B scenarios, the account and parent accounts - **Customer**: The logged-in customer's segment - **Tags**: Custom context tags for advanced segmentation This context is provided via request headers and is used to resolve the appropriate catalog rules and price books. ### Admin vs Shopper Endpoints - **Shopper endpoints** (`/pcm/catalog/search`, `/pcm/catalog/multi-search`): Use shopper context headers to automatically resolve the correct catalog and prices. - **Admin endpoints** (`/pcm/catalogs/{catalog_id}/releases/{release_id}/search`): Directly specify the catalog and release to search, useful for previewing releases or testing. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Searchable Fields The Searchable Fields API returns a list of all fields available for searching, filtering, faceting, and sorting in your search queries. This includes both the standard product fields that are indexed by default and any custom fields you've added through Indexable Fields. ### Using Searchable Fields Use this endpoint to: - **Discover available fields**: See all fields that can be used in search queries - **Build dynamic UIs**: Programmatically generate filter and facet options based on available fields - **Validate configurations**: Verify that your indexable fields have been properly added to the schema ### Field Properties Each searchable field includes: | Property | Description | | --- | --- | | `name` | The field name to use in search queries | | `type` | The data type (`string`, `int32`, `int64`, `float`, `bool`) | | `facetable` | Whether the field can be used for faceting | | `sortable` | Whether the field can be used for sorting | | `locale` | The language code for text fields | ### Standard vs Custom Fields - **Standard fields**: Built-in fields like `name`, `description`, `sku`, `meta.search.nodes.name` that are always available - **Custom fields**: Fields added through Indexable Fields from your product extensions ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Set search profile as default import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Set a search profile as the default. Request Mens Shoes` && meta.display_price.without_tax.float_price:>100\").\nThese profile-level filters are ANDed with any filters provided in the search request via the filter_by parameter, resulting in: (profile_filter1 || profile_filter2 || ... profile_filterN) && request_filters.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"exclusions":{"type":"array","description":"A collection of exclusion expressions to apply to search results. Multiple exclusions in the array are combined using OR logic (records matching exclusion1 || exclusion2 || ... exclusionN).","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"boosts":{"type":"array","items":{"type":"object","description":"Defines a boosting rule that assigns a score to products matching a specific field value.","required":["condition","weight"],"properties":{"condition":{"type":"string","description":"A filter expression used to identify a subset of products for boosting. This follows the standard filter_by syntax.\n\nIt can be a simple condition like `meta.search.nodes.name:=\\`Electronics\\`` or complex like `meta.search.nodes.name:=\\`Electronics\\` && extensions.products(Details).brand:=Nike`.\n","minLength":1,"example":"meta.search.nodes.name:=\\`Electronics\\`"},"weight":{"type":"integer","description":"A numerical value representing the boost intensity. Products matching the criteria are assigned this value. Higher weights will cause products to appear earlier in the results.\n\n**Impact of Weights:**\n* **Boost (Positive):** Pushes products to the top.\n* **No affect (Zero):** Has no affect. Treated the same as products that match no rules.\n* **Bury (Negative):** Pushes products to the bottom.\n\n**Rule Evaluation:** The system uses \"Short-circuit\" evaluation. The engine stops at the **first matching rule**.\nThis means the weight of the first matching rule will be used as the product weight to sort the results.\nIf no rules match, the product is assigned a weight of `0`.\n","example":5}},"title":"SearchBoostRule"},"x-go-type-skip-optional-pointer":true},"prefix":{"type":"boolean","description":"Profile-level default for prefix (partial match) behavior on the last query token. When true, the last word in the query is treated as a prefix for all fields that do not have an explicit per-field prefix value. For example, a search request for \"red app\" matches \"red apple\". When false, the last word must match exactly. If omitted, default of true applies. Per-field prefix values override this setting.\nThe primary use case is to show results as the user is typing in the search box.\n","example":true},"typo_tolerance":{"type":"object","nullable":true,"description":"Optional typo tolerance configuration applied at search time.\nAll fields are optional; defaults are noted on each field.\n","properties":{"num_typos":{"type":"integer","description":"Profile-level default for the maximum number of typographical errors\n[Damerau-Levenshtein distance](https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance) allowed when matching any field.\nAccepted values: 0 (exact match only), 1, or 2.\nPer-field `num_typos` values override this setting. If omitted, default of 2 applies.\n\nFor example, a search request for \"red appla\" matches \"red apple\" with a `num_typos` of 1.\n\n**`num_typos` is an upper bound, not a guarantee.** The number of corrections actually\napplied to a query token is also capped by its length via\n`min_len_to_allow_single_character_correction` (default 4) and\n`min_len_to_allow_two_character_correction` (default 7): a token shorter than the\nsingle-character threshold gets no correction at all, and a token shorter than the\ntwo-character threshold is corrected by at most one character — even when `num_typos` is 2.\nSee those two fields for details.\n","minimum":0,"maximum":2,"example":1},"min_len_to_allow_single_character_correction":{"type":"integer","description":"Minimum query-token length required before a single-character typo correction is attempted. This works together with `num_typos`: a token shorter than this length receives no typo correction at all, regardless of `num_typos`. For example, when set to 4, a search for \"appla\" will match \"apple\", but a search for \"apa\" will not match \"app\" because the length of \"apa\" is 3.\nDefault: 4.\n","minimum":1,"example":3},"min_len_to_allow_two_character_correction":{"type":"integer","description":"Minimum query-token length required before a two-character typo correction is attempted. This works together with `num_typos`: even when `num_typos` is 2, a token shorter than this length is corrected by at most one character (and a token shorter than `min_len_to_allow_single_character_correction` is not corrected at all). For example, with the default of 7, the 7-character query \"monetar\" can be corrected to \"monitor\" (two corrections), but a 6-character query with two mistakes cannot.\nDefault: 7\n","minimum":1,"example":7},"typo_tokens_threshold":{"type":"integer","description":"Typo-corrected query variations are only generated if the number of exact results\nfound is fewer than this value. Set to 0 to disable typo tolerance entirely.\nFor example, when set to 5 and the search result only has 3 results, the search engine will apply typo correction to try to return 5 or more results.\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_threshold":{"type":"integer","description":"For multi-word queries, tokens are progressively dropped if the number of results\nis fewer than this value. Set to 0 to disable token dropping.\n\nFor example, when set to 5 and the search result only has 3 results for \"red apple\" search,\nthe search engine will drop the last token \"apple\" and find more results with just by searching for \"red\".\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_mode":{"type":"string","description":"Controls the direction in which tokens are dropped from a multi-word query when\nresults fall below drop_tokens_threshold.\n- `right_to_left` (default): drops tokens from the right end of the query first.\n- `left_to_right`: drops tokens from the left end first.\n- `both_sides:N`: drops from both ends, limited to queries of N tokens or fewer\n (e.g. `both_sides:3` applies only to queries with 3 or fewer tokens).\n","example":"right_to_left"},"enable_typos_for_numerical_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that are purely numeric (every character is a digit, e.g. \"98765\"). Such a token must then match exactly.\nDefault: true\n","example":true},"enable_typos_for_special_char_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that contain at least one non-alphanumeric character\n(any character outside `a-z`, `A-Z`, `0-9`), forcing such tokens to match exactly.\nUseful for keeping product codes / SKUs precise.\n\nTokens like `abc-123`, `abc-def`, `123-456`, and `v1.2.0` are affected;\na plain alphanumeric token like `abc123` is not.\n\nNote: the special character must be indexed on the field (via `symbols_to_index`);\notherwise the search engine removes the special characters from tokens\n(e.g. a token like v1.2.0 becomes v120) and it no longer qualifies.\n\nDefault: true\n","example":true},"split_join_tokens":{"type":"string","description":"Controls whether compound words and multi-word phrases are treated as equivalent during search.\nFor example, a query for \"nonstick\" may also match \"non stick\", and vice versa.\n- `fallback` (default): tries the original query form first; falls back to split/joined variants if results are insufficient.\n- `always`: always generates both split and joined token variants alongside the original query.\n- `off`: disables split/join token handling.\n","enum":["fallback","always","off"],"example":"fallback"}},"title":"TypoTolerance"},"synonym_settings":{"type":"object","nullable":true,"description":"Optional synonym tuning applied at search time. These settings control how synonym\nmatches are ranked and how query tokens are resolved against the synonym sets attached\nto the search profile. All fields are optional; defaults are noted on each field.\nThey only have an observable effect when synonym sets are attached to the resolved profile.\n","properties":{"demote_synonym_match":{"type":"boolean","description":"When true, results matched via a synonym are ranked below direct (non-synonym) matches. When false, synonym matches and direct matches are ranked equally.\nDefault: false\n","example":true},"synonym_resolution_allowed_on_prefix":{"type":"boolean","description":"When true, an incomplete (prefix) query token can resolve to a synonym, i.e. synonym\nexpansion is attempted on prefix tokens.\n\n**This is not the same as the `prefix` setting.** The `prefix` setting treats only the\n**last** word of the query as a prefix; `synonym_resolution_allowed_on_prefix` applies\nprefix matching at **every** token position when looking words up in the synonym sets —\nthere is no last-token special-casing.\n\n**Exact matches always win.** A query token that exactly equals a synonym key resolves\nregardless of this flag; the prefix behavior only affects the fuzzy fallback for tokens\nwith no exact synonym-key match. It composes with\n`number_of_typos_allowed_when_resolving_synonyms`, which governs typo tolerance during\nthe prefix/fuzzy lookup.\n\nWorked example (synonym keys `red`, `apple`, `apparel`):\n- `red app`: `red` matches exactly; `app` prefix-matches both `apple` and `apparel` — both expand.\n- `re app`: `re` prefix-matches `red` **and** `app` prefix-matches `apple`/`apparel` — both expand.\n The regular `prefix` setting would only treat the last word (`app`) as a prefix; here every\n position is prefix-matched.\n\nDefault: false\n","example":true},"number_of_typos_allowed_when_resolving_synonyms":{"type":"integer","description":"Number of typos allowed when resolving synonyms. Enables fuzzy synonym matching\nso that a misspelled query term can still trigger a synonym expansion for the\nsynonym sets attached to the search profile.\nAccepted values: 0 (exact synonym match only, default), 1, or 2.\n","minimum":0,"maximum":2,"example":0}},"title":"SynonymSettings"},"synonym_sets":{"type":"array","description":"Optional list of synonym set IDs to apply at search time. Each synonym set must exist and must have been synced to the search engine at least once. Organization-level search profiles may only reference organization-level synonym sets. Store-level search profiles may reference organization-level and same-store synonym sets.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","format":"uuid","example":"3fa85f64-5717-4562-b3fc-2c963f66afa6"}},"force_use_default_price_for_faceting_and_sorting":{"type":"boolean","description":"When set to true, the default price is used for faceting and sorting for segmented catalogs even if the catalog rule has a supported price book.","default":false,"example":true}},"title":"SearchProfileAttributes"},"meta":{"type":"object","required":["default","owner"],"properties":{"default":{"type":"boolean","description":"Whether this is the default search profile.","example":true},"owner":{"description":"The resource owner, either `organization` or `store`.","type":"string","example":"organization","enum":["organization","store"],"x-go-type":"tenancy.Owner","x-go-type-import":{"path":"gitlab.elasticpath.com/commerce-cloud/ncl-projects/paragon/catalog-search.svc/internal/domain/tenancy"},"title":"ResourceOwner"}},"title":"SearchProfileMeta"}},"title":"SearchProfile"}},"title":"SearchProfileResponse"}}}},"400":{"description":"Bad request - invalid parameters","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"}}}},"403":{"description":"Permission denied - search profile owned by the organization","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"}}}},"404":{"description":"Search profile not found","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"},"examples":{"internal-server-error":{"value":{"errors":[{"title":"Internal Server Error","status":"500"}]}}}}}}}} > --- ## Stopword Sets Stopword Sets allow you to define sets of common words (such as "the", "a", "an", "is") that should be ignored during search queries. By removing these low-value terms from search processing, you can improve search relevance and reduce noise in results. ### How Stopword Sets Work A stopword set is a named container of stopword words. Each set belongs to an organization or store and is synced asynchronously. Once synced, the stopwords are applied during search query processing to filter out the specified terms. ### Common Stopwords Stopword sets contain a flat list of words to ignore: - **Common articles**: "the", "a", "an" - **Prepositions**: "in", "on", "at", "for" - **Conjunctions**: "and", "or", "but" ### Sync Status Stopword sets are synced asynchronously. The sync status is tracked and exposed in API responses: | Status | Description | |------------------|----------------------------------------------------------------| | `pending_sync` | Set has been created or updated in MongoDB but not yet synced | | `synced` | Set has been successfully synced | | `sync_failed` | The last sync attempt failed | | `pending_delete` | Set is marked for deletion; a background worker will remove it | ### Tenancy Stopword sets follow the same tenancy model as other resources: - **Organization-scoped sets**: Managed by the organization; apply across all stores - **Store-scoped sets**: Managed by the store; apply only to that store Stores cannot modify organization-scoped stopword sets. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Synonym Sets Synonym Sets allow you to define groups of equivalent or related terms so that searches for one term also return results for its synonyms. This helps shoppers find products regardless of the specific terminology they use. ### How Synonym Sets Work A synonym set is a named container of synonym items. Each set belongs to an organization or store and is synced asynchronously. Once synced, a set can be attached to one or more search profiles; its synonym rules are then applied during searches that use those profiles to expand queries with matching terms. ### Synonym Types Each item within a synonym set can be either multi-way or one-way: - **Multi-way synonyms**: All terms are treated as equivalent. Searching for any term in the list returns results for all of them. For example, `["sneakers", "trainers", "running shoes"]` means a search for "trainers" also returns results for "sneakers" and "running shoes". - **One-way synonyms**: Searches for a `root` term also match the `synonyms`, but not vice versa. For example, with `root: "jacket"` and `synonyms: ["blazer", "coat"]`, searching for "jacket" also returns results for "blazer" and "coat", but searching for "blazer" does not return results for "jacket". ### Synonym Item Configuration Each item within a synonym set supports the following options: | Option | Required | Description | |--------------------|----------|--------------------------------------------------------------------------------------------------------------| | `id` | Yes | Unique identifier for the item within the set. Alphanumeric characters, hyphens, and underscores only. | | `synonyms` | Yes | List of synonym terms. Minimum 1 if `root` is provided (one-way), minimum 2 if `root` is absent (multi-way). | | `root` | No | Makes this a one-way synonym. Must not also appear in the `synonyms` array. | | `locale` | No | ISO 639 language code for this synonym item. | | `symbols_to_index` | No | Special characters to preserve as part of tokens. Each element must be exactly one character. | ### Sync Status Synonym sets are synced asynchronously. The sync status is tracked and exposed in API responses: | Status | Description | |------------------|----------------------------------------------------------------| | `pending_sync` | Set has been created or updated in MongoDB but not yet synced | | `synced` | Set has been successfully synced | | `sync_failed` | The last sync attempt failed | | `pending_delete` | Set is marked for deletion; a background worker will remove it | ### Tenancy Synonym sets follow the same tenancy model as other resources: - **Organization-scoped sets**: Managed by the organization; apply across all stores - **Store-scoped sets**: Managed by the store; apply only to that store Stores cannot modify organization-scoped synonym sets. ### Using Synonym Sets in Search Profiles Synonym sets only take effect once they are attached to a [search profile](/docs/api/pxm/catalog-search/search-profiles) via its `synonym_sets` attribute. At search time, the synonym sets of the resolved search profile are applied to the query. When attaching a synonym set to a search profile: - The set must exist and be accessible by the calling tenant. Organization-level search profiles may only reference organization-level sets; store-level search profiles may reference organization-level and same-store sets. - The set must have been synced at least once. A set in `pending_sync` or `sync_failed` state can still be used if it was previously synced — its last synced state continues to apply. A synonym set cannot be deleted while it is referenced by any search profile; the delete request is rejected with a `409 Conflict` until the reference is removed. ### Use Cases - **Regional terminology**: Map British and American English terms (e.g., "trousers" ↔ "pants") - **Brand equivalents**: Link product category names with common alternatives - **Industry jargon**: Ensure technical terms match colloquial ones - **Abbreviations**: Map abbreviations to their full forms (e.g., "tee" → "t-shirt") ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Update indexable fields import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update additional fields to be indexed. Request ).` — indexes a field from a product extension template. The field must exist and be enabled in the flows service.\n- **Shopper attribute fields**: `shopper_attributes.` — indexes a merchant-defined shopper attribute. Always typed as `string`. The attribute name must be no longer than **64 characters** and can only contain alphanumeric characters, underscores (`_`), and hyphens (`-`).\n- **Admin attribute fields**: `admin_attributes.` — indexes a merchant-defined admin attribute. Always typed as `string`. The attribute name must be no longer than **64 characters** and can only contain alphanumeric characters, underscores (`_`), and hyphens (`-`).\n","example":"extensions.products(clothing).color","minLength":1},"facetable":{"type":"boolean","description":"Enables faceting on the field.","default":false,"example":true},"sortable":{"type":"boolean","description":"When set to true, the field will be sortable. Default: true for numbers, false otherwise.","example":true},"locale":{"type":"string","description":"For configuring language specific tokenization, e.g. jp for Japanese. Default: en which also broadly supports most European languages. For valid values, see [ISO 639 language codes](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes).","default":"en","example":"en"},"stem":{"type":"boolean","description":"When true, enables word stemming on this field using [Snowball stemmer](https://snowballstem.org/). Stemming reduces words to their root form at index and query time, so a search for \"running\" will also match products containing \"run\", \"runs\", or \"runner\". This improves search recall for descriptive text fields where shoppers may use different word forms than those used in product data. Only valid for string-typed fields. Defaults to false.\n","example":true,"title":"Stem"},"token_separators":{"type":"array","x-go-type-skip-optional-pointer":true,"items":{"type":"string","minLength":1,"maxLength":1},"description":"Per-field token separators for this field. Overrides the collection-level token_separators for this field. An empty array defers to the collection-level setting. Each element must be a single character.\nFor example, take text `non-tech`. By default, it will be tokenized to `nontech`. So, search for `non tech` will not match the product. Set `token_separators: [\"-\"]`. Then it will be tokenized to `non` and `tech`. Now, search for both `non-tech` and `non tech` will match this product.\n"},"symbols_to_index":{"type":"array","x-go-type-skip-optional-pointer":true,"items":{"type":"string","minLength":1,"maxLength":1},"description":"By default, special characters are removed from fields when indexing and searching for them. Provide per-field special characters to index for this field. Overrides the collection-level symbols_to_index for this field. An empty array defers to the collection-level setting. Each element must be a single character.\n"}},"title":"IndexableFieldRequest"},"example":[{"name":"extensions.products(clothing).color","facetable":false,"sortable":false,"locale":"en"},{"name":"shopper_attributes.fabric","facetable":false,"sortable":false},{"name":"admin_attributes.internal_grade","sortable":true}]},"core_field_overrides":{"type":"array","description":"Per-field configuration for core product fields (e.g. name, description).","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Name of the core field to configure. Must be one of the supported core fields.\n","example":"name"},"stem":{"type":"boolean","description":"When true, enables word stemming on this field using [Snowball stemmer](https://snowballstem.org/). Stemming reduces words to their root form at index and query time, so a search for \"running\" will also match products containing \"run\", \"runs\", or \"runner\". This improves search recall for descriptive text fields where shoppers may use different word forms than those used in product data. Only valid for string-typed fields. Defaults to false.\n","example":true,"title":"Stem"},"token_separators":{"type":"array","x-go-type-skip-optional-pointer":true,"items":{"type":"string","minLength":1,"maxLength":1},"description":"Per-field token separators for this core field. Overrides the collection-level token_separators for this field. An empty array defers to the collection-level setting. Each element must be a single character.\nFor example, take text `non-tech`. By default, it will be tokenized to `nontech`. So, search for `non tech` will not match the product. Set `token_separators: [\"-\"]`. Then it will be tokenized to `non` and `tech`. Now, search for both `non-tech` and `non tech` will match this product.\n"},"symbols_to_index":{"type":"array","x-go-type-skip-optional-pointer":true,"items":{"type":"string","minLength":1,"maxLength":1},"description":"By default, special characters are removed from fields when indexing and searching for them. Provide per-field special characters to index for this core field. Overrides the collection-level symbols_to_index for this field. An empty array defers to the collection-level setting. Each element must be a single character.\n"},"sortable":{"type":"boolean","description":"When set to true, enables sorting on this core field. Only supported for specific core fields.\n","example":true},"facetable":{"type":"boolean","description":"When set to true, enables faceting on this core field. A re-index is required for the change to take effect.\n","example":true}},"title":"CoreFieldOverride"}},"token_separators":{"type":"array","items":{"type":"string","minLength":1,"maxLength":1},"description":"Characters to use as token separators across all the index fields, in addition to spaces and newlines. Each element must be a single character. Defaults to none set.\nFor example, take text `non-tech`. By default, it will be tokenized to `nontech`. So, search for `non tech` will not match the product. Set `token_separators: [\"-\"]`. Then it will be tokenized to `non` and `tech`. Now, search for both `non-tech` and `non tech` will match this product.\n"},"symbols_to_index":{"type":"array","items":{"type":"string","minLength":1,"maxLength":1},"description":"By default, special characters are removed from fields when indexing and searching for them. Provide list of special characters that should be indexed as part of the tokens across the all index fields. Each element must be a single character. Defaults to none set.\n"}},"title":"IndexableFieldsRequestAttributes"}},"title":"IndexableFieldsUpdateRequestData"}},"title":"IndexableFieldsUpdateRequest"}}}}} > --- ## Update search profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a search profile. Request Mens Shoes` && meta.display_price.without_tax.float_price:>100\").\nThese profile-level filters are ANDed with any filters provided in the search request via the filter_by parameter, resulting in: (profile_filter1 || profile_filter2 || ... profile_filterN) && request_filters.\n","items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"exclusions":{"type":"array","description":"A collection of exclusion expressions to apply to search results. Multiple exclusions in the array are combined using OR logic (records matching exclusion1 || exclusion2 || ... exclusionN).","items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"boosts":{"type":"array","items":{"type":"object","description":"Defines a boosting rule that assigns a score to products matching a specific field value.","required":["condition","weight"],"properties":{"condition":{"type":"string","description":"A filter expression used to identify a subset of products for boosting. This follows the standard filter_by syntax.\n\nIt can be a simple condition like `meta.search.nodes.name:=\\`Electronics\\`` or complex like `meta.search.nodes.name:=\\`Electronics\\` && extensions.products(Details).brand:=Nike`.\n","minLength":1,"example":"meta.search.nodes.name:=\\`Electronics\\`"},"weight":{"type":"integer","description":"A numerical value representing the boost intensity. Products matching the criteria are assigned this value. Higher weights will cause products to appear earlier in the results.\n\n**Impact of Weights:**\n* **Boost (Positive):** Pushes products to the top.\n* **No affect (Zero):** Has no affect. Treated the same as products that match no rules.\n* **Bury (Negative):** Pushes products to the bottom.\n\n**Rule Evaluation:** The system uses \"Short-circuit\" evaluation. The engine stops at the **first matching rule**.\nThis means the weight of the first matching rule will be used as the product weight to sort the results.\nIf no rules match, the product is assigned a weight of `0`.\n","example":5}},"title":"SearchBoostRule"}},"prefix":{"type":"boolean","nullable":true,"description":"Profile-level default for prefix (partial match) behavior on the last query token. When true, the last word in the query is treated as a prefix for all fields that do not have an explicit per-field prefix value. For example, a search request for \"red app\" matches \"red apple\". When false, the last word must match exactly. If omitted, default of true applies. Per-field prefix values override this setting.\nThe primary use case is to show results as the user is typing in the search box.\n","example":true},"typo_tolerance":{"type":"object","nullable":true,"description":"Optional typo tolerance configuration applied at search time.\nAll fields are optional; defaults are noted on each field.\n","properties":{"num_typos":{"type":"integer","description":"Profile-level default for the maximum number of typographical errors\n[Damerau-Levenshtein distance](https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance) allowed when matching any field.\nAccepted values: 0 (exact match only), 1, or 2.\nPer-field `num_typos` values override this setting. If omitted, default of 2 applies.\n\nFor example, a search request for \"red appla\" matches \"red apple\" with a `num_typos` of 1.\n\n**`num_typos` is an upper bound, not a guarantee.** The number of corrections actually\napplied to a query token is also capped by its length via\n`min_len_to_allow_single_character_correction` (default 4) and\n`min_len_to_allow_two_character_correction` (default 7): a token shorter than the\nsingle-character threshold gets no correction at all, and a token shorter than the\ntwo-character threshold is corrected by at most one character — even when `num_typos` is 2.\nSee those two fields for details.\n","minimum":0,"maximum":2,"example":1},"min_len_to_allow_single_character_correction":{"type":"integer","description":"Minimum query-token length required before a single-character typo correction is attempted. This works together with `num_typos`: a token shorter than this length receives no typo correction at all, regardless of `num_typos`. For example, when set to 4, a search for \"appla\" will match \"apple\", but a search for \"apa\" will not match \"app\" because the length of \"apa\" is 3.\nDefault: 4.\n","minimum":1,"example":3},"min_len_to_allow_two_character_correction":{"type":"integer","description":"Minimum query-token length required before a two-character typo correction is attempted. This works together with `num_typos`: even when `num_typos` is 2, a token shorter than this length is corrected by at most one character (and a token shorter than `min_len_to_allow_single_character_correction` is not corrected at all). For example, with the default of 7, the 7-character query \"monetar\" can be corrected to \"monitor\" (two corrections), but a 6-character query with two mistakes cannot.\nDefault: 7\n","minimum":1,"example":7},"typo_tokens_threshold":{"type":"integer","description":"Typo-corrected query variations are only generated if the number of exact results\nfound is fewer than this value. Set to 0 to disable typo tolerance entirely.\nFor example, when set to 5 and the search result only has 3 results, the search engine will apply typo correction to try to return 5 or more results.\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_threshold":{"type":"integer","description":"For multi-word queries, tokens are progressively dropped if the number of results\nis fewer than this value. Set to 0 to disable token dropping.\n\nFor example, when set to 5 and the search result only has 3 results for \"red apple\" search,\nthe search engine will drop the last token \"apple\" and find more results with just by searching for \"red\".\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_mode":{"type":"string","description":"Controls the direction in which tokens are dropped from a multi-word query when\nresults fall below drop_tokens_threshold.\n- `right_to_left` (default): drops tokens from the right end of the query first.\n- `left_to_right`: drops tokens from the left end first.\n- `both_sides:N`: drops from both ends, limited to queries of N tokens or fewer\n (e.g. `both_sides:3` applies only to queries with 3 or fewer tokens).\n","example":"right_to_left"},"enable_typos_for_numerical_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that are purely numeric (every character is a digit, e.g. \"98765\"). Such a token must then match exactly.\nDefault: true\n","example":true},"enable_typos_for_special_char_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that contain at least one non-alphanumeric character\n(any character outside `a-z`, `A-Z`, `0-9`), forcing such tokens to match exactly.\nUseful for keeping product codes / SKUs precise.\n\nTokens like `abc-123`, `abc-def`, `123-456`, and `v1.2.0` are affected;\na plain alphanumeric token like `abc123` is not.\n\nNote: the special character must be indexed on the field (via `symbols_to_index`);\notherwise the search engine removes the special characters from tokens\n(e.g. a token like v1.2.0 becomes v120) and it no longer qualifies.\n\nDefault: true\n","example":true},"split_join_tokens":{"type":"string","description":"Controls whether compound words and multi-word phrases are treated as equivalent during search.\nFor example, a query for \"nonstick\" may also match \"non stick\", and vice versa.\n- `fallback` (default): tries the original query form first; falls back to split/joined variants if results are insufficient.\n- `always`: always generates both split and joined token variants alongside the original query.\n- `off`: disables split/join token handling.\n","enum":["fallback","always","off"],"example":"fallback"}},"title":"TypoTolerance"},"synonym_settings":{"type":"object","nullable":true,"description":"Optional synonym tuning applied at search time. These settings control how synonym\nmatches are ranked and how query tokens are resolved against the synonym sets attached\nto the search profile. All fields are optional; defaults are noted on each field.\nThey only have an observable effect when synonym sets are attached to the resolved profile.\n","properties":{"demote_synonym_match":{"type":"boolean","description":"When true, results matched via a synonym are ranked below direct (non-synonym) matches. When false, synonym matches and direct matches are ranked equally.\nDefault: false\n","example":true},"synonym_resolution_allowed_on_prefix":{"type":"boolean","description":"When true, an incomplete (prefix) query token can resolve to a synonym, i.e. synonym\nexpansion is attempted on prefix tokens.\n\n**This is not the same as the `prefix` setting.** The `prefix` setting treats only the\n**last** word of the query as a prefix; `synonym_resolution_allowed_on_prefix` applies\nprefix matching at **every** token position when looking words up in the synonym sets —\nthere is no last-token special-casing.\n\n**Exact matches always win.** A query token that exactly equals a synonym key resolves\nregardless of this flag; the prefix behavior only affects the fuzzy fallback for tokens\nwith no exact synonym-key match. It composes with\n`number_of_typos_allowed_when_resolving_synonyms`, which governs typo tolerance during\nthe prefix/fuzzy lookup.\n\nWorked example (synonym keys `red`, `apple`, `apparel`):\n- `red app`: `red` matches exactly; `app` prefix-matches both `apple` and `apparel` — both expand.\n- `re app`: `re` prefix-matches `red` **and** `app` prefix-matches `apple`/`apparel` — both expand.\n The regular `prefix` setting would only treat the last word (`app`) as a prefix; here every\n position is prefix-matched.\n\nDefault: false\n","example":true},"number_of_typos_allowed_when_resolving_synonyms":{"type":"integer","description":"Number of typos allowed when resolving synonyms. Enables fuzzy synonym matching\nso that a misspelled query term can still trigger a synonym expansion for the\nsynonym sets attached to the search profile.\nAccepted values: 0 (exact synonym match only, default), 1, or 2.\n","minimum":0,"maximum":2,"example":0}},"title":"SynonymSettings"},"synonym_sets":{"type":"array","description":"Optional list of synonym set IDs to apply at search time. Each synonym set must exist and must have been synced to the search engine at least once. Organization-level search profiles may only reference organization-level synonym sets. Store-level search profiles may reference organization-level and same-store synonym sets. Set to an empty array to remove all synonym sets from the search profile.\n","items":{"type":"string","format":"uuid","example":"3fa85f64-5717-4562-b3fc-2c963f66afa6"}},"force_use_default_price_for_faceting_and_sorting":{"type":"boolean","description":"When set to true, the default price is used for faceting and sorting for segmented catalogs even if the catalog rule has a supported price book.","example":true}},"title":"SearchProfileUpdateAttributes"}},"title":"SearchProfileUpdateRequestData"}},"title":"SearchProfileUpdateRequest"}}}}} > Mens Shoes` && meta.display_price.without_tax.float_price:>100\").\nThese profile-level filters are ANDed with any filters provided in the search request via the filter_by parameter, resulting in: (profile_filter1 || profile_filter2 || ... profile_filterN) && request_filters.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"exclusions":{"type":"array","description":"A collection of exclusion expressions to apply to search results. Multiple exclusions in the array are combined using OR logic (records matching exclusion1 || exclusion2 || ... exclusionN).","x-go-type-skip-optional-pointer":true,"items":{"type":"string","example":"meta.search.categories.lvl1:=`All Products > Mens Shoes`","minLength":1}},"boosts":{"type":"array","items":{"type":"object","description":"Defines a boosting rule that assigns a score to products matching a specific field value.","required":["condition","weight"],"properties":{"condition":{"type":"string","description":"A filter expression used to identify a subset of products for boosting. This follows the standard filter_by syntax.\n\nIt can be a simple condition like `meta.search.nodes.name:=\\`Electronics\\`` or complex like `meta.search.nodes.name:=\\`Electronics\\` && extensions.products(Details).brand:=Nike`.\n","minLength":1,"example":"meta.search.nodes.name:=\\`Electronics\\`"},"weight":{"type":"integer","description":"A numerical value representing the boost intensity. Products matching the criteria are assigned this value. Higher weights will cause products to appear earlier in the results.\n\n**Impact of Weights:**\n* **Boost (Positive):** Pushes products to the top.\n* **No affect (Zero):** Has no affect. Treated the same as products that match no rules.\n* **Bury (Negative):** Pushes products to the bottom.\n\n**Rule Evaluation:** The system uses \"Short-circuit\" evaluation. The engine stops at the **first matching rule**.\nThis means the weight of the first matching rule will be used as the product weight to sort the results.\nIf no rules match, the product is assigned a weight of `0`.\n","example":5}},"title":"SearchBoostRule"},"x-go-type-skip-optional-pointer":true},"prefix":{"type":"boolean","description":"Profile-level default for prefix (partial match) behavior on the last query token. When true, the last word in the query is treated as a prefix for all fields that do not have an explicit per-field prefix value. For example, a search request for \"red app\" matches \"red apple\". When false, the last word must match exactly. If omitted, default of true applies. Per-field prefix values override this setting.\nThe primary use case is to show results as the user is typing in the search box.\n","example":true},"typo_tolerance":{"type":"object","nullable":true,"description":"Optional typo tolerance configuration applied at search time.\nAll fields are optional; defaults are noted on each field.\n","properties":{"num_typos":{"type":"integer","description":"Profile-level default for the maximum number of typographical errors\n[Damerau-Levenshtein distance](https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance) allowed when matching any field.\nAccepted values: 0 (exact match only), 1, or 2.\nPer-field `num_typos` values override this setting. If omitted, default of 2 applies.\n\nFor example, a search request for \"red appla\" matches \"red apple\" with a `num_typos` of 1.\n\n**`num_typos` is an upper bound, not a guarantee.** The number of corrections actually\napplied to a query token is also capped by its length via\n`min_len_to_allow_single_character_correction` (default 4) and\n`min_len_to_allow_two_character_correction` (default 7): a token shorter than the\nsingle-character threshold gets no correction at all, and a token shorter than the\ntwo-character threshold is corrected by at most one character — even when `num_typos` is 2.\nSee those two fields for details.\n","minimum":0,"maximum":2,"example":1},"min_len_to_allow_single_character_correction":{"type":"integer","description":"Minimum query-token length required before a single-character typo correction is attempted. This works together with `num_typos`: a token shorter than this length receives no typo correction at all, regardless of `num_typos`. For example, when set to 4, a search for \"appla\" will match \"apple\", but a search for \"apa\" will not match \"app\" because the length of \"apa\" is 3.\nDefault: 4.\n","minimum":1,"example":3},"min_len_to_allow_two_character_correction":{"type":"integer","description":"Minimum query-token length required before a two-character typo correction is attempted. This works together with `num_typos`: even when `num_typos` is 2, a token shorter than this length is corrected by at most one character (and a token shorter than `min_len_to_allow_single_character_correction` is not corrected at all). For example, with the default of 7, the 7-character query \"monetar\" can be corrected to \"monitor\" (two corrections), but a 6-character query with two mistakes cannot.\nDefault: 7\n","minimum":1,"example":7},"typo_tokens_threshold":{"type":"integer","description":"Typo-corrected query variations are only generated if the number of exact results\nfound is fewer than this value. Set to 0 to disable typo tolerance entirely.\nFor example, when set to 5 and the search result only has 3 results, the search engine will apply typo correction to try to return 5 or more results.\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_threshold":{"type":"integer","description":"For multi-word queries, tokens are progressively dropped if the number of results\nis fewer than this value. Set to 0 to disable token dropping.\n\nFor example, when set to 5 and the search result only has 3 results for \"red apple\" search,\nthe search engine will drop the last token \"apple\" and find more results with just by searching for \"red\".\n\nDefault: 1\n","minimum":0,"example":1},"drop_tokens_mode":{"type":"string","description":"Controls the direction in which tokens are dropped from a multi-word query when\nresults fall below drop_tokens_threshold.\n- `right_to_left` (default): drops tokens from the right end of the query first.\n- `left_to_right`: drops tokens from the left end first.\n- `both_sides:N`: drops from both ends, limited to queries of N tokens or fewer\n (e.g. `both_sides:3` applies only to queries with 3 or fewer tokens).\n","example":"right_to_left"},"enable_typos_for_numerical_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that are purely numeric (every character is a digit, e.g. \"98765\"). Such a token must then match exactly.\nDefault: true\n","example":true},"enable_typos_for_special_char_tokens":{"type":"boolean","description":"When false, typo tolerance is disabled for query tokens that contain at least one non-alphanumeric character\n(any character outside `a-z`, `A-Z`, `0-9`), forcing such tokens to match exactly.\nUseful for keeping product codes / SKUs precise.\n\nTokens like `abc-123`, `abc-def`, `123-456`, and `v1.2.0` are affected;\na plain alphanumeric token like `abc123` is not.\n\nNote: the special character must be indexed on the field (via `symbols_to_index`);\notherwise the search engine removes the special characters from tokens\n(e.g. a token like v1.2.0 becomes v120) and it no longer qualifies.\n\nDefault: true\n","example":true},"split_join_tokens":{"type":"string","description":"Controls whether compound words and multi-word phrases are treated as equivalent during search.\nFor example, a query for \"nonstick\" may also match \"non stick\", and vice versa.\n- `fallback` (default): tries the original query form first; falls back to split/joined variants if results are insufficient.\n- `always`: always generates both split and joined token variants alongside the original query.\n- `off`: disables split/join token handling.\n","enum":["fallback","always","off"],"example":"fallback"}},"title":"TypoTolerance"},"synonym_settings":{"type":"object","nullable":true,"description":"Optional synonym tuning applied at search time. These settings control how synonym\nmatches are ranked and how query tokens are resolved against the synonym sets attached\nto the search profile. All fields are optional; defaults are noted on each field.\nThey only have an observable effect when synonym sets are attached to the resolved profile.\n","properties":{"demote_synonym_match":{"type":"boolean","description":"When true, results matched via a synonym are ranked below direct (non-synonym) matches. When false, synonym matches and direct matches are ranked equally.\nDefault: false\n","example":true},"synonym_resolution_allowed_on_prefix":{"type":"boolean","description":"When true, an incomplete (prefix) query token can resolve to a synonym, i.e. synonym\nexpansion is attempted on prefix tokens.\n\n**This is not the same as the `prefix` setting.** The `prefix` setting treats only the\n**last** word of the query as a prefix; `synonym_resolution_allowed_on_prefix` applies\nprefix matching at **every** token position when looking words up in the synonym sets —\nthere is no last-token special-casing.\n\n**Exact matches always win.** A query token that exactly equals a synonym key resolves\nregardless of this flag; the prefix behavior only affects the fuzzy fallback for tokens\nwith no exact synonym-key match. It composes with\n`number_of_typos_allowed_when_resolving_synonyms`, which governs typo tolerance during\nthe prefix/fuzzy lookup.\n\nWorked example (synonym keys `red`, `apple`, `apparel`):\n- `red app`: `red` matches exactly; `app` prefix-matches both `apple` and `apparel` — both expand.\n- `re app`: `re` prefix-matches `red` **and** `app` prefix-matches `apple`/`apparel` — both expand.\n The regular `prefix` setting would only treat the last word (`app`) as a prefix; here every\n position is prefix-matched.\n\nDefault: false\n","example":true},"number_of_typos_allowed_when_resolving_synonyms":{"type":"integer","description":"Number of typos allowed when resolving synonyms. Enables fuzzy synonym matching\nso that a misspelled query term can still trigger a synonym expansion for the\nsynonym sets attached to the search profile.\nAccepted values: 0 (exact synonym match only, default), 1, or 2.\n","minimum":0,"maximum":2,"example":0}},"title":"SynonymSettings"},"synonym_sets":{"type":"array","description":"Optional list of synonym set IDs to apply at search time. Each synonym set must exist and must have been synced to the search engine at least once. Organization-level search profiles may only reference organization-level synonym sets. Store-level search profiles may reference organization-level and same-store synonym sets.\n","x-go-type-skip-optional-pointer":true,"items":{"type":"string","format":"uuid","example":"3fa85f64-5717-4562-b3fc-2c963f66afa6"}},"force_use_default_price_for_faceting_and_sorting":{"type":"boolean","description":"When set to true, the default price is used for faceting and sorting for segmented catalogs even if the catalog rule has a supported price book.","default":false,"example":true}},"title":"SearchProfileAttributes"},"meta":{"type":"object","required":["default","owner"],"properties":{"default":{"type":"boolean","description":"Whether this is the default search profile.","example":true},"owner":{"description":"The resource owner, either `organization` or `store`.","type":"string","example":"organization","enum":["organization","store"],"x-go-type":"tenancy.Owner","x-go-type-import":{"path":"gitlab.elasticpath.com/commerce-cloud/ncl-projects/paragon/catalog-search.svc/internal/domain/tenancy"},"title":"ResourceOwner"}},"title":"SearchProfileMeta"}},"title":"SearchProfile"}},"title":"SearchProfileResponse"}}}},"400":{"description":"Bad request - invalid parameters","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"}}}},"403":{"description":"Permission denied - search profile owned by the organization","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"}}}},"404":{"description":"Search profile not found","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}},"title":"Error"}}},"title":"ErrorResponse"},"examples":{"internal-server-error":{"value":{"errors":[{"title":"Internal Server Error","status":"500"}]}}}}}}}} > --- ## Update stopword set import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update the stopwords in an existing stopwords set. The locale cannot be changed. Request --- ## Update synonym set import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a synonym set by ID. Request --- ## Create a Currency import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a currency. Request --- ## Currencies Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; In your store, you can display prices to customers in their local currency. You can configure up to ten currencies per store. Configure currencies only for the locales in which you do business, and select one of the currencies to be the default currency. If a default currency is not selected, the store uses the United States Dollar (USD). After a customer selects a locale, the product prices in the catalog, carts, and orders are displayed in the currency for that locale. Order totals and taxes are calculated in the same currency. You cannot have a cart or order where product prices are in mixed currencies. Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: URL: [https://elasticpath.com](https://elasticpath.com) License MIT --- ## Currencies :::caution - There is a hard limit of 10 currencies per store. ::: ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Delete a Currency import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a currency. :::caution - You can’t delete a default currency. ::: Request --- ## Get a Currency import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Fetch a currency by its ID. Request --- ## Get all Currencies import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Fetch all currencies. Request --- ## Update a Currency import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a currency. Request --- ## Create a File import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a File Request --- ## Delete a File import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a File Request --- ## Files Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Products are the items or services that you might want to sell in your store. In Product Experience Manager, products can also have associated rich media assets, such as product images or a file containing additional product details. You can do this using the Files API. Once you have created your files, you associate the files with your products using the [Create Product-File Relationships API](/docs/api/pxm/products/create-product-file-relationships). Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Files You can upload image files or URLs by using `multipart/form-data` as the content type header. For example, `"Content-Type: multipart/form-data" \`. Commerce supports the following file types. | File Extension | Description | | --- | --- | | .gif | Graphics Interchange Format (GIF) | | .jpg/jpeg | Joint Photographic Experts Group (JPEG) format | | .png | Portable graphics format | | .webp | Web picture format | | .mp4 | Moving Picture Experts Group (MPEG) format | | .mov | QuickTime Movie format | | .pdf | Portable Document Format | | .usdz | Universal Scene Description Format | | .glb | Global File format | | .jp2 | Compressed bitmap image saved in Joint Photographic Experts Group (JPEG) format | | .jxr | Extended range for Joint Photographic Experts Group (JPEG) format | | .aac | Advanced Audio Coding (AAC) format | | .vrml | Virtual Reality Modelling Language (VRML) format | | .doc(x) | Microsoft Word Open XML format | | .ppt(x) | Microsoft PowerPoint Open XML format | | .xls(x) | Microsoft Excel Open XML format | By default, the maximum file size is 8MB. If you need to support larger file sizes, contact your Elastic Path representative. Alternatively, store files somewhere else and reference them. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Get a File import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a File Request --- ## Get all Files import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves all files. ### Filtering For general filtering syntax, see [Filtering](/guides/Getting-Started/filtering). The following operators and attributes are available when filtering on this endpoint. | Attribute | Type | Operators | Example | |:----------------------|:----------|:--------------------------|:-------------| | `id` | `string` | `in` | `in(id,file-id-1,file-id-2,file-id-3)` | | `file_name` | `string` | `eq` / `like` | `eq(file_name, my_image.jpg)` | | `width` | `integer` | `gt` / `ge` / `lt` / `le` | `gt(width,200)` | | `height` | `integer` | `gt` / `ge` / `lt` / `le` | `lt(height,500)` | | `file_size` | `integer` | `gt` / `ge` / `lt` / `le` | `le(file_size,20953)` | #### Bulk File Retrieval To retrieve multiple files by their IDs in a single request, use the `in` operator with a comma-separated list of file IDs: ``` GET /v2/files?filter=in(id,06b881bd-f152-4c36-8658-7132a8fab49c,ec73567b-04e8-4000-a11a-7e1407cc2f21) ``` This is more efficient than making separate requests for each file and is recommended for bulk operations. **Note on invalid IDs**: If any IDs in the filter are missing, malformed, or do not exist in the store, they will be silently ignored. The response will only include files that were successfully found. For example, if you request 5 IDs but only 3 exist, the response will contain 3 files with `total: 3` in the metadata. Request --- ## Create Stock for Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Sets the inventory quantity for the specified product. When you take this action, you are choosing to manage the inventory for this product in Commerce. Request --- ## Delete Stock for Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes the inventory for the specified product. The product inventory is null and is no longer managed by Commerce. If you want to keep managing inventory but have none of the product in stock, set the inventory to `0` instead of deleting the inventory. Request --- ## Get Stock for Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Gets the stock for the product matching the specified unique identifier. Request --- ## Get Single Stock Transaction for Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the specific transaction with transaction_uuid for product_uuid Request --- ## Get Stock for all Products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns all products and their associated stock. Request --- ## Get Stock for Multiple Products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns stock for all products matching the supplied unique identifiers. Request --- ## Get Stock Transactions for Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the transactions recorded for the specified product. Request --- ## Inventories Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; The Inventory API allows you to manage stock for products at both organization and store levels. :::note This basic version of inventories service does not support multi-location inventory. To access the newer location-aware interface to this service one must pass the following HTTP header when making API requests: ``` EP-Inventories-Multi-Location: true ``` Please refer to the [Multi-location Inventory API](/docs/api/pxm/inventory_mli) documentation as the interface is not entirely compatible with that described here. ::: Inventory is the quantity of each product that you have in stock. The inventory service allows you and your business to keep track of inventory, including a transactional historic log. Inventory for each product is tracked using the following values: - **Total**: The amount of product in stock. (Total = Available + Allocated) - **Available**: The amount of product available in stock minus allocated products. (Available = Total - Allocated) - **Allocated**: The amount of reserved product in stock. :::note In Commerce Manager, you can manage the inventory while creating a new product in Product Experience Manager. Go to **Products** > **Inventory** and you can specify the inventory details (**allocate**, **deallocate**, **increment**, and **decrement**). ::: ### Order flow There are three mandatory steps to complete an order in relation to inventory: 1. Added to a cart 2. Checked out 3. Paid 4. Shipped (optional) #### Unpaid order flow The following flowchart depicts the process of an unpaid order. ![The order is created from the cart during the checkout process.](/assets/order-flow.png) #### Payment flow The following flowchart depicts the process of paying for an order. ![The payment workflow.](/assets/payment-workflow-1.png) ### How stock is managed Stock is managed as follows: 1. When a customer attempts to add products to a cart, the inventory service checks if there is enough available stock. If there is not enough stock available, you receive a 400 HTTP response with a warning. The response does not describe what products cannot be added, nor does it return how many products are in stock. 2. If a customer successfully adds products to a cart, the customer can checkout to create an unpaid order. 3. A final check on the available stock is performed. 4. After creating the unpaid order, the payment for an order can be taken. When a customer attempts to pay for an order, the inventory service reserves the stock before the payment is processed internally. At any time before the point of payment, a customer might lose their order, if the customer is slower than everyone else. If the payment fails, the temporary stock allocation is removed, and the stock becomes available again for anyone to buy. If the payment succeeds, that stock is still allocated, and the items belong to the customer, unless for any reason they are reallocated before shipment. For example, if the customer cancels, or you realize the order is fraudulent, then you can reallocate the inventory. 5. Finally, when the order is marked as shipped, that stock is fully decremented. This means the allocation number is reduced, and therefore the total, and the products are no longer in the warehouse. During split payments, stocks are allocated only if the first transaction for an order is complete. If the transaction fails, the stocks are deallocated. Once the first transaction is complete, the stocks are not allocated for the subsequent transactions as they are already reserved for the order. The stocks are deallocated and return to available when the the order is canceled. ### Implications of the inventories API - It is possible for more products to be in carts than there are in stock if the `add to cart` request quantity is less than available stocks. For example, when available stocks are 100, a user can add 60 to cart 1 and then 50 to cart 1, or user A can add 80 to cart 1, while user B can add 30 to cart 2. - It is possible for more products to be checked out than there are in stock if the `add to cart` request quantity is less than the available stocks. - It is not possible for more stock to be paid for than is in stock. - It is a race for your customers to pay for an order, and whoever does not pay fast enough, is left disappointed. Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Inventory The Inventory API allows you to manage stock for products at both organization and store levels. Each product keeps a history of inventory transactions, enabling easier stock auditing. You can specify an initial stock level when you create a product. The stock is set to `0` by default. :::caution You cannot create multiple inventories of the same organization-level product in different stores because no unique stock ID, specific to each store, is currently generated. Hence, when you try to manage inventory of the same product for different stores, you get an invalid product identifier error. ::: ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Transactions Methods to allow you to modify and view a products stock via transactions. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Create Stock Transaction on Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create Stock Transaction on Product Request --- ## Import a dataset import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Import a dataset Request --- ## Create a Location import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Creates an Inventory Location Request --- ## Create Stock for Product(Inventory_mli) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Sets the inventory quantity for the specified product. Request --- ## Create Stock Transaction on Product(Inventory_mli) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create Stock Transaction on Product Request --- ## Delete a Location import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete an Inventory Location Request --- ## Delete Stock for Product(Inventory_mli) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes the inventory for the specified product. The product inventory is null and is no longer managed by Commerce. If you want to keep managing inventory but have none of the product in stock, set the inventory to `0` instead of deleting the inventory. Request --- ## Get import errors import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves all errors encountered as part of the import. Each error is attributed to a line in the JSONL file imported, so for example, if at line 1 in your JSONL you had a stock without locations, there would be a missing key error for locations. Errors are also ordered by line number ascending, and can be paginated. Request --- ## Get import import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the import job for the specified ID. Request --- ## Get a Location import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get an Inventory Location Request --- ## List Stock import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns stock for all products matching the supplied unique identifiers. Request --- ## Get Stock for Product(Inventory_mli) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Gets the stock for the product matching the specified unique identifier. Request --- ## Get Single Stock Transaction for Product(Inventory_mli) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the specific transaction with transaction_uuid for product_uuid Request --- ## Imports You can import stock positions for up to 50,000 products in a single operation via an import. This is useful for synchronosing external systems with Elastic Path. The API uses a [**JSONL**](https://jsonlines.org/) file, with one line per product. For each product one specifies the total stock in each location. For example ``` {"data":{"type":"stock","id":"b36ba644-6fdc-49b3-9ebb-410ed34908a8","attributes":{"locations":{"vancouver":{"total":20}}}}} {"data":{"type":"stock","id":"2e5a4c7b-6f88-4aad-a3c2-4d8b29bc32a4","attributes":{"locations":{"vancouver":{"total":54},"denver":{"total":1},"boston":{"total":20},"portland":{"total":100}}}}} ``` ### Characteristics of Inventories Import The Inventories Import API has the following characteristics: - The Inventories Import API reads the entire file and then updates the inventory. - Inventories imports are asynchronous and are processed one at a time. You can continue to send import requests, but these are queued. - If a product in an import does not already exist in the inventories database it will be created. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Inventories Introduction(Inventory_mli) import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; The Inventory API allows you to manage stock for products at both organization and store levels. Stock can be optionally managed in [multiple locations](#multi-location-inventories) representing different stores or warehouses. :::note This version of the inventories service is not entirely compatible with the [basic version](/docs/api/pxm/inventory) and so must be enabled by setting the following HTTP header when making requests: ``` EP-Inventories-Multi-Location: true ``` The two systems operate on the same database and may be used interchangeably for stock that does not use multiple locations. ::: Inventory is the quantity of each product that you have in stock. The inventory service allows you and your business to keep track of inventory, including a transactional historic log. Inventory for each product is tracked using the following values: - **Total**: The amount of product in stock. (Total = Available + Allocated) - **Available**: The amount of product available in stock minus allocated products. (Available = Total - Allocated) - **Allocated**: The amount of reserved product in stock. :::note In Commerce Manager, you can manage the inventory while creating a new product in Product Experience Manager. Go to **Products** > **Inventory** and you can specify the inventory details (**allocate**, **deallocate**, **increment**, and **decrement**). ::: ### Order flow There are three mandatory steps to complete an order in relation to inventory: 1. Added to a cart 2. Checked out 3. Paid 4. Shipped (optional) #### Unpaid order flow The following flowchart depicts the process of an unpaid order. ![The order is created from the cart during the checkout process.](/assets/order-flow.png) #### Payment flow The following flowchart depicts the process of paying for an order. ![The payment workflow.](/assets/payment-workflow-1.png) ### How stock is managed Stock is managed as follows: 1. When a customer attempts to add products to a cart, the inventory service checks if there is enough available stock. If there is not enough stock available, you receive a 400 HTTP response with a warning. The response does not describe what products cannot be added, nor does it return how many products are in stock. 2. If a customer successfully adds products to a cart, the customer can checkout to create an unpaid order. 3. A final check on the available stock is performed. 4. After creating the unpaid order, the payment for an order can be taken. When a customer attempts to pay for an order, the inventory service reserves the stock before the payment is processed internally. At any time before the point of payment, a customer might lose their order, if the customer is slower than everyone else. If the payment fails, the temporary stock allocation is removed, and the stock becomes available again for anyone to buy. If the payment succeeds, that stock is still allocated, and the items belong to the customer, unless for any reason they are reallocated before shipment. For example, if the customer cancels, or you realize the order is fraudulent, then you can reallocate the inventory. 5. Finally, when the order is marked as shipped, that stock is fully decremented. This means the allocation number is reduced, and therefore the total, and the products are no longer in the warehouse. During split payments, stocks are allocated only if the first transaction for an order is complete. If the transaction fails, the stocks are deallocated. Once the first transaction is complete, the stocks are not allocated for the subsequent transactions as they are already reserved for the order. The stocks are deallocated and return to available when the order is canceled. ### Implications of the inventories API - It is possible for more products to be in carts than there are in stock if the `add to cart` request quantity is less than available stocks. For example, when available stocks are 100, a user can add 60 to cart 1 and then 50 to cart 1, or user A can add 80 to cart 1, while user B can add 30 to cart 2. - It is possible for more products to be checked out than there are in stock if the `add to cart` request quantity is less than the available stocks. - It is not possible for more stock to be paid for than is in stock. - It is a race for your customers to pay for an order, and whoever does not pay fast enough, is left disappointed. ### Multi-location inventories If you wish to manage stock in multiple locations you can [create a number of locations](/docs/api/pxm/inventory_mli/create-location) and then when [creating stock inventory](/docs/api/pxm/inventory_mli/create-stock), specify a different stock position for each location. Then, when adding to cart, one can specify the location that will supply the inventory for that product and the system will manage stock in that location, checking stock levels and allocating and decrementing the correct stock position through the life cycle of the order. Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Inventory(Inventory_mli) The Inventory API allows you to manage stock for products at both organization and store levels. Each product keeps a history of inventory transactions, enabling easier stock auditing. You can specify an initial stock level when you create a product. The stock is set to `0` by default. :::caution You cannot create multiple inventories of the same organization-level product in different stores because no unique stock ID, specific to each store, is currently generated. Hence, when you try to manage inventory of the same product for different stores, you get an invalid product identifier error. ::: ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## List import jobs import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all import jobs. Request --- ## List Locations import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Lists all Inventory Locations Request --- ## Get Stock for all Products(Inventory_mli) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns all products and their associated stock. Request --- ## Get Stock Transactions for Product(Inventory_mli) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the transactions recorded for the specified product. Request --- ## Transactions(Inventory_mli) Methods to allow you to modify and view a products stock via transactions. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Update a Location import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Updates an Inventory Location Request --- ## Update Stock for Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Updates the inventory for the specified product. Request --- ## Create a Modifier import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can use price modifiers to change the price property of child products. By default, child products inherit the same price as their base products. Using price modifiers, you can enable child products to inherit a different price. This enables you to configure the price of child products, for example, to be lower than its base product, without having to individually update the price of your child products. There are three types of price modifier. Request --- ## Create a Price Book import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Creates a price book. You can add the prices to the price book now or update the price book later. Request --- ## Add a Product Price to a Price Book import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Price books contain prices for the products in your catalog. Use the Prices API to adds the prices for a product to a specified price book. If the prices for the product already exist in the price book, the operation fails and the existing product prices are not updated. Request --- ## Delete a Modifier import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes the specified price book modifier. Request --- ## Delete a Price Book by ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes the specified price book and all prices in the price book. It does not delete the products. In addition, pricing details in the orders referring to the deleted price book are not deleted. Request --- ## Delete a Product Price from a Price Book import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes a product price from the specified price book. Request --- ## Get a Modifier import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the specified price book modifier from the specified price book. Request --- ## Gets a list of all modifiers import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of price modifiers for the specified price book. ### Filtering Filtering is supported on this endpoint. For the general syntax, see [Filtering](/guides/Getting-Started/filtering). You can filter on the following attributes and operators. | Operator | Attribute | Description | Example | | --- | --- | --- | --- | | `eq` | `external_ref`, `name` | Checks if the values you provide matches a price modifier. | `filter=eq(name,largesupplement)` | Request --- ## Get a Price Book by ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the specified price book. To include prices in the response, append `?include=prices` to the path. Request --- ## Get all Price Books import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all price books. ### Filtering Filtering is supported on this endpoint. For the general syntax, see [Filtering](/guides/Getting-Started/filtering). You can filter on the following attributes and operators. | Operator | Attribute | Description | Example | | --- | --- | --- | --- | | `eq` | `external_ref` | Equals. Checks if the values you provide matches a price book. | `filter=eq(external_ref,some-external-ref)` | Request --- ## Gets all Prices import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Allows you to retrieve all prices for a product, irrespective of the different price books that include that product's price. For example, you can filter for all prices for a specified `sku`, or filter for all prices changed before or after a given date. This will retrieve prices from all price books. ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). | Operator | Attribute | Description | Example | | --- | --- | --- | --- | | `eq` | `external_ref`, `sku`, `id` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | `filter=eq(sku,some-sku)` | | `in` | `external_ref`, `sku`, `id` | In. Checks if the values are included in the specified list. If they are, the condition is true. | `filter=in(sku,some-sku)` | | `like` | `external_ref`, `sku` | Like. Checks if the operand contains the specified string. Wildcards are supported. | `filter=like(sku,some-sku)` | | `gt` | `updated_at`, `created_at` | Greater than. Checks if the value on the left of the operator is greater than the value on the right. If it is, the condition is true. | `filter=gt(updated_at,2018-04-16T10:11:59.715Z)` | | `lt` | `updated_at`, `created_at` | Less than. Checks if the value on the left of the operator is less than the value on the right. If it is, the condition is true. | `filter=lt(updated_at,2018-04-16T10:11:59.715Z)` | Request --- ## Get a Product Price by Price Book ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a specified product price (`priceId`) in the specified price book (`id`). Request --- ## Gets all Prices by Price Book ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves all the product prices in the specified price book. ### Filtering This endpoint supports filtering. For general syntax, see [Filtering](/guides/Getting-Started/filtering). | Operator | Attribute | Description | Example | | --- | --- | --- | --- | | `eq` | `external_ref`, `sku` | Checks if the values you provide matches a price. | `filter=eq(sku,some-sku)` | | `in` | `sku` | Checks if the values you provide are included in a product SKU. | `filter=in(sku,some-sku)' | Request --- ## Import a Price Book and Prices You can create and update product price books and prices in bulk, at both organization and store level, using the Price Book Import API. This is useful, for example, if you have a promotion and want to update 50,000 product prices. Rather than having to go to each price book and manually edit 50,000 prices, you can use the Price Book Import API to bulk update all your product prices at the same time, including setting different prices for different currencies. You can create/update: - price books. - prices. - sales pricing for products and product bundles with SKUs. - volume pricing (tiers). The following are not supported by the Price Book Import API: - price modifiers - SKUless bundles - Bundle sale prices The API uses a [JSONL](https://jsonlines.org/) file. The JSONL file can be compressed to a GZIP file. Here is an [example of a JSONL file](/assets/example_file_all.jsonl). A file can include up to 50,000 objects. If you have more than 50,000 objects, then you must create a separate file, and import each file, one at a time. ### Characteristics of Price Book Import The Price Book Import API reads the entire file and then creates/updates the price book objects. This means the price book objects can be in any order in the file. Price book imports are asynchronous. When you send a request to the price book import API, it triggers an asynchronous job to create/update the price books and product prices. You can see the status of a job using Get a job. Jobs are processed one at a time. You can continue to send price book import requests, but those jobs are queued. In other words, Commerce looks for any jobs that have a status of PENDING and starts the job with the earliest created date. This process is repeated until all jobs are processed. See [Jobs](/docs/api/pxm/products/jobs). The API works on a "best endeavours" approach. In other words, the API does its best to create/update the price book objects based on the file that you provide. You can then use the results of the job to understand what objects the API created/updated and to troubleshoot any errors. See [Price Book Import API Results](#price-book-import-api-results). Price book imports are processed sequentially in the order that you send your import API requests. ### Price Book Import Unique Identifiers The API uses unique identifiers to identify the objects to be created/updated. You must provide either an `id` or an `external_ref`. You may have both, but you must have at least one. - If you supply an `id` then the ID must exist for the object to be updated. If the ID does not exist, this causes an error. - If you supply an `external_ref` then the API checks if the external reference exists and updates the object. If the external reference does not exist, the API creates a new object with the external reference you have specified. #### Price Book Unique Identifiers The following table describes the unique identifiers you must provide, depending on whether you are creating or updating a price book. | Action | Unique Identifiers | | --- | --- | | Creating | Unique price book name.`external_ref` for the price book. | | Updating | `id` and/or `external_ref` for the price book. | #### Price Unique Identifiers The following table describes the unique identifiers you must provide, depending on whether you are creating or updating a price. | Action | Unique Identifiers | | --- | --- | | Creating | The product SKU that the price belongs to.`id` and/or `external_ref` for the price book where you want to create the new price.`external_ref` for the price. The `external_ref` for a price must be unique within a price book. However, you can have duplicate price external references across multiple price books. | | Updating | The product SKU that the price belongs to.`pricebook_external_ref` for the price book where you want to update the new price.`id` and/or `external_ref` for the price. The `external_ref` for a price must be unique within a price book. However, you can have duplicate price external references across multiple price books. | ### Price Book Import File You can create/update price book objects using [Import a Price](/docs/api/pxm/pricebooks/import-a-price-book-and-prices). The API uses a [JSONL](https://jsonlines.org/) file. The JSONL file can be compressed to a GZIP file. Here is an [example of a JSONL file](/assets/example_file_all.jsonl). A file can include up to 50,000 objects. If you have more than 50,000 objects, then you must create a separate file, and import each file, one at a time. - The `pricebook` Object - The attributes you can specify for a `pricebook` object are the attributes you specify when [creating a pricebook](/docs/api/pxm/pricebooks/create-pricebook). - The `product-price` Object - The attributes you can specify for a `product-price` object are the attributes you specify when [adding a price to a price book](/docs/api/pxm/pricebooks/create-product-price). Once your import file is created, use the [import a price book and prices API to import](/docs/api/pxm/pricebooks/import-pricebook) the file. ### Importing product prices with custom attributes There are two types of custom attributes a price can have `shopper_attributes` and `admin_attributes`. When importing product prices with custom attributes, you can import a price with: - up to 100 `admin_attributes` - up to 100 `shopper_attributes` Ensure that a price adheres to these limits for custom attributes. ### Price Book Import API Results The API works on a "best endeavours" approach. In other words, the API does its best to create/update the price book objects based on the file that you provide. If there are any errors, then the import is aborted and the job fails with an error. You can then use the job results to understand what objects the API created/updated until the import failed and to troubleshoot any errors. Once you have fixed any errors, you can then use the [**import a price**](/docs/api/pxm/pricebooks/import-pricebook) endpoint to send the request again. The following table describes the import messages reported by the API. | Import Message | Description | | --- | --- | | import price book_id: '%v' belongs to Organization", price book.ID))"import price book external_ref: '%v' belongs to Organization", *price book.ExternalRef) | This group of messages tells you that these imported objects belong to an organization. | matched price with pricebook_id - had different external_refmatched price with pricebook_id - belongs to different price bookmatched price with pricebook_id - price_id not foundmatched price with pricebook_id - price_id belongs to an organization.matched price with pricebook_id - duplicate external_ref detectedmatched price with pricebook_id - duplicate SKU detected - required SKU. | This group of messages is telling you that the price was updated but there is an issue with another attribute that requires fixing. | The following table describes the import errors reported by the API. | Error | Description | | --- | --- | | error processing gzip fileerror processing object '%v' invalid json provided | This group of errors indicates that there is a problem with the JSONL file. You must fix the problems with the file and try the import again. | | duplicate price book Id '%s' in imported price booksmissing attributes for price bookinvalid type for external_ref for price bookmissing attributes for pricemissing sku for pricemissing sku for priceinvalid type for external_ref for priceinvalid type for sku for pricemissing price book_id/price book_external_ref for priceprice book id(s) not foundprice book external ref(s) not foundprice book id not found:duplicate external ref foundprice Ids not foundprice book external refs not found | This group of errors indicates that there is some information missing from the objects you are trying to create/update. | ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Import a Price import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can create and update product price books and prices in bulk, at both organization and store level, using the Price Book Import API. This is useful, for example, if you have a promotion and want to update 50,000 product prices. Rather than having to go to each price book and manually edit 50,000 prices, you can use the Price Book Import API to bulk update all your product prices at the same time, including setting different prices for different currencies. The API uses a [JSONL](https://jsonlines.org/) file. The JSONL file can be compressed to a GZIP file. Here is an [example of a JSONL file](/assets/example_file_all.jsonl). The API works on a "best endeavours" approach. In other words, the API does its best to create/update the price book objects based on the file that you provide. If there are any errors, then the import is aborted, and the job fails with an error. You can then use the job results to understand what objects the API created/updated until the import failed, and to troubleshoot any errors. See [Import Results](#tag/Price-Book-Import). Price book imports are processed sequentially in the order that you send your import API requests. --- ## Price Book Modifiers You can use price modifiers to change the price property of child products. By default, child products inherit the same price as their base products. Using price modifiers, you can enable child products to inherit a different price. This enables you to configure the price of child products, for example, to be lower than its base product, without having to individually update the price of your child products. There are three types of price modifier. | Modifier | Data Type | Effect | |:------------------|:----------|:---------------------------------------------| | `price_increment` | `string` | Increases the price of a product. | | `price_decrement` | `string` | Decreases the price of a product. | | `price_equals` | `string` | Sets the price of a product to the amount you specify. | The following is an overview of the steps you need to follow to use price modifiers. 1. Create a price modifier. You must give the price modifier a unique name. For more information, see [Create a Price Modifier](/docs/api/pxm/pricebooks/create-price-modifier). 1. Build your child products with the new product modifier. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Price Books Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; You can use the price books service to configure your product pricing. Your price books are associated with your catalogs. Creating separate price books enables you to: - Maintain consistent and accurate pricing across all your product listings and channels. - Provide competitive pricing by creating different price books for different channels. For example, different pricing for different geographical regions, based on standard of living costs. - Provide personalized pricing by creating personalized price books. For example, pricing for loyalty customers versus new customers. - Enable cross-selling and upselling by offering sales and volume pricing for your products. - Create price-books based on real-time adjustments such as inventory levels and market conditions. Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Price Books Price books contain prices for the products in your catalog. Each catalog must have one price book. In your storefront, the product prices are displayed in the currency for the selected locale. If a product in the catalog does not have a price in the price book, the product is displayed without a price. A price book can be associated with multiple catalogs. Following on from this, you can associate more than one price book with a catalog. Price book stacking allows you to create multiple price books for different scenarios, such as seasonal sales, business versus retail customer pricing, and reward programs. If you have multiple price books, when you create a catalog, you must configure a priority for your price books. Product prices are displayed in the catalog according to the priority of the price books. For example, you may have products that have different prices based on region. You can have a price book with the standard retail pricing and then have a second price book that has different pricing for a different region. See Create a catalog. A price book contains a list of product SKUs and the prices you want to charge for those products. If your store supports multiple locales, a price book can contain product prices in each of the supported currencies. In addition, you can configure sales and volume (tier) pricing. :::note Price books work with products that are defined using the Product Experience Manager resource model. If your products are defined using an earlier Products resource model, you will need to migrate products to the `pcm/products` resource before you implement price books. ::: You can duplicate an existing price book and create a new price book. All products and prices associated with the price book are copied to the new price book. Based on the business requirements, you can use the same data or update the data. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Prices Price books contain prices for the products in your catalog. Use the Price Books API to create price books and add product prices to the price book. ### Volume (tiers) Pricing Using volume (tiers) pricing allows your store to offer different pricing for minimum quantities of items that your customers purchase. When a customer adds sufficient quantity of an item and meets the minimum required quantity for different pricing, all products with that item SKU are discounted in the cart. You can define the price range for different quantities of different items as in the following example: | Quantity | Price/Each | |:---------|:-----------| | 1-5 | $10.50 | | 6-10 | $10.00 | | 11-20 | $9.50 | | 21-50 | $8.50 | | 51+ | $7.90 | ### Sales Pricing With sales pricing, a store can optionally add a sale price to a product price. For example, a store can schedule seasonal pricing on products without creating a new price book and catalog ruleset. Optionally, a store can schedule the date ranges for the sale products. You can set a sale price for an item within a bundle so that the product is sold at the sale price when sold as part of the bundle. For example, if you have a bundle consisting of four items, you can apply a discounted price to an item within the bundle to get a bundle sales price. 1. For sale prices in the same price book: - the schedules must not be exactly the same. - schedules can partially overlap. If the schedule does contain overlapping sales prices, the sale price of the smallest sale period is chosen. - if you have just one sale price, without a schedule, this is effectively a permanent price. If you want to add more sale prices to the price book, you must configure a schedule for the sale price. 2. Sale prices in different price books can have overlapping schedules. Both list and sale price (or was/is prices) are available in the catalog response, enabling you to display slash pricing on your storefront, depending on your requirements. ### Creating a bundle sale price You can assign a sale price to an option in a bundle. 1. In the product price book, create a sale. 2. Specify the bundle ID that contains the option you want to provide a sale price for. 3. Provide the sale price for the option. You can add the same sale price for the same option using an array of bundle_ids if you want to sell the product as part of different bundles. ### Understanding Volume and Sale Pricing Behavior for Products If you have configured both sale and volume pricing for your products and product bundles, the following table describes how pricing behaves in the following scenarios. | Scenario | Description | | --- | --- | | Minimum quantities for volume pricing and sale pricing | (With sale schedule) If you have specified a minimum quantity of five whose price is $0.99 and at the same time, you have configured a sale for the time of purchase, then when a shopper checks out with 5 or more items, the total is based on the volume pricing. In other words, $0.99 × 5 = $4.95. Additionally, if volume pricing exist for both the product price and the sale, the volume pricing for the sale takes precedence. If no volume pricing is set in the sale, the base sale price is applied, and the volume pricing for the product price will not be applied.(With sale schedule) If a shopper's items in the cart do not meet the minimum quantity required for volume pricing, the total is calculated based on the sales price.(Without sale schedule) If the sale is a permanent sale and volume pricing is only set for the product price, then regardless of the quantity a shopper adds to a cart, the final price is always calculated based on the base sales price. However, if volume pricing has been set for the sale, the final price will be determined by the volume tier pricing set in the sale, not the base sales price. | Two levels of volume pricing with different prices for each volume. | If you have configured two levels of volume pricing, for example, the first minimum quantity is 5 and the second minimum quantity is 10:When the quantity in the cart is => 5, then the price for the minimum quantity of 5 is used.When the quantity in the cart is => 10 then the price for the minimum quantity of 10 is used. | ### Optimizing product prices You can add custom attributes to a product price, allowing your storefront to dynamically use these attributes in it's pricing and display logic. This enables you to optimize your pricing data, enhancing your ability to respond to market dynamics and customer preferences. Some examples of pricing optimization strategies are: - dynamic pricing - allows you to change the price of a product based on changes in customer demand, for example, raising prices during the high-demand holiday season or segment-focused, like special offers for new customers. - value-based pricing - allows you to offer different pricing tiers, for example, "pro" features cost more. - cost-plus pricing - allows you to set prices by adding a specific percentage to the production cost of a single unit. There are two types of custom attributes: - `admin_attributes` - `admin_attributes` are not displayed in catalogs. This means `admin-attributes` can only be viewed by administrators. For example, you may want to add custom attributes that can automate price updates based on predefined rules, saving time and reducing human error or you might want to integrate price attributes with your other company systems, (ERP, CRM) ensuring consistency and accuracy across platforms. - `shopper_attributes` - `shopper_attributes` are displayed in catalogs. This means `shopper_attributes` can be viewed by both shoppers and administrators. For example, you can set prices based on customer segments, offering different prices for wholesale and retail customers or providing discounts to loyal customers. Both `admin-attributes` and `shopper_attributes` are structured as key-value pairs. Both the keys and values are `strings`. You can have up to 100 keys for each type of attribute. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Replicate a Price Book import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Using this endpoint, you can replicate an existing price book. This is useful because it enables you to quickly and easily create multiple price books with the same pricing structure. When you replicate an existing price book, you can specify a new name, description, and external reference for the replicated price book. Other attributes stay the same. Request --- ## Update a Modifier import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the price modifier is not updated. Request --- ## Update a Price Book by ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Updates the specified price book. Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the price book is not updated. Request --- ## Update a Product Price in a Price Book import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the price is not updated. Request --- ## Attach Custom Relationships to a Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can attach up to 5 custom relationships to a product. Once you have attached a custom relationship to a product, you can then create relationships from a product to one or many other products. See [Associate a product to one or more products using a custom relationship](/docs/api/pxm/products/product-association-id). See [Custom Relationships](/guides/key-concepts/product-experience-manager/custom-relationships/). ### Prerequisites - A Custom Relationship has been created, see [create a Custom Relationship](/docs/api/pxm/products/create-custom-relationship), - A Product has been created. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Attach multiple nodes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Assigns products to multiple hierarchies and their children nodes. You can apply a filter to search for the appropriate products to attach to a node. For general filtering syntax, see [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | Example | | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `eq` | `id`, `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `name`, `templates`, `commodity_type`, `owner`, `product_types`, `parent_id`, `component_option_id`, `tags`, `status`, `has_nodes (false only)`, `created_at`, `updated_at`, `external_ref`, `description` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. For `product_types`, you can only specify one product type. **Note:** `has_nodes` can only be filtered as `false`. **Note:** `component_option_id` matches when a bundle includes that product id as a component option. | `?filter=eq(name,some-name)` | | `like` | `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `name`, `tags`, `description`, `external_ref` | Like. Checks if the operand contains the specified string. Wildcards are supported. | `?filter=like(name,*some-name*)` | | `in` | `id`, `name`, `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `product_types`, `parent_id`, `component_option_id`, `tags`, `external_ref` | Checks if the values are included in the specified list. If they are, the condition is true. For `product_types`, you can specify more than one product type. | `?filter=in(id,some-id)` | | `gt` | `id`, `created_at`, `updated_at`, `external_ref` | Greater than. Checks if the value of the field is greater than the given value. | `?filter=gt(updated_at,2024-01-01T00:00:00Z)` | | `ge` | `id`, `created_at`, `updated_at`, `external_ref` | Greater than or equal to. Checks if the value of the field is greater than or equal to the given value. | `?filter=ge(created_at,2023-01-01T00:00:00Z)` | | `lt` | `id`, `created_at`, `updated_at`, `external_ref` | Less than. Checks if the value of the field is less than the given value. | `?filter=lt(updated_at,2025-01-01T00:00:00Z)` | | `le` | `id`, `created_at`, `updated_at`, `external_ref` | Less than or equal to. Checks if the value of the field is less than or equal to the given value. | `?filter=le(created_at,2022-01-01T00:00:00Z)` | | `eq` (extensions) | `extensions.book.isbn` | Filters using a nested extension field. | `?filter=eq(extensions.book.isbn,1765426)` | | `eq` (shopper_attributes) | `shopper_attributes.color` | Filters using a shopper custom attribute field. | `?filter=eq(shopper_attributes.color,red)` | | `eq` (admin_attributes) | `admin_attributes.warehouse` | Filters using an admin custom attribute field. | `?filter=eq(admin_attributes.warehouse,US-EAST)` | Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Build child products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; With product variations in Product Experience Manager, you can create product variations and different options for each variation and use both to create child products for a product. Each child product is a unique combination of options associated with the product. Child products inherit attributes from their parent products. When you make changes to the attributes of the parent products, you can rebuild your child products, ensuring that changes to the parent products are propagated to the child products. Alternatively, you can modify a child product independently, without impacting its parent product. For example, you may prefer the status of your child product to be `live`, while keeping the parent product's status as `draft`. When you directly update a child product, it becomes independent of its parent product. In other words, any subsequent changes made to the parent product are not automatically reflected in the child product when you rebuild the parent product and its child products. Once a child product is independent of its parent, you cannot recreate the association between the child product and its parent. You must delete the child product and rebuild the parent to recreate the child product. Following on from that, if you add the same flow to both a parent and child product, the child flow values are not affected by changes to the parent flow values in a rebuild. ### Using Build Rules When building your child products, you can build all products related to a product. Alternatively, you can build a combination of child products associated with a product, based on build rules that you specify. This is useful, for example, if you have a variation option that you do not sell. This makes managing and building your child products quick and easy. You can do this using `build_rules`. `build_rules` are combinations of variation option IDs that you wish to include or exclude when building your child products. :::note You do not need to configure any `build_rules` in the following scenarios: - Child products must be built with all variation options. Simply, use the `Create a product` or `Update a product` endpoints with no `build_rules` specified. - Child products must be built apart from all options for a specific variation. In this case, you must remove the variation and use the `Create a product` or `Update a product` endpoints with no `build_rules` specified. In other words, using our example, if none of the `size` options should be included, then remove the `size` variation. ::: The `build_rules` contain: - (Required) `default`: specifies the default behavior. - (Optional) `include`: specifies the option IDs to include when the child products are built. Each combination consists of a nested array of option IDs from one or more variations. Combinations of option IDs in the nested arrays must come from different variations. See [**Invalid Build Rules**](#invalid-build-rules). - (Optional) `exclude`: specifies the option IDs to exclude when the child products are built. Each combination consists of a nested array of option IDs from one or more variations. Combinations of option IDs in the nested arrays must come from different variations. See [**Invalid build rules**](#invalid-build-rules). When building child products, Commerce compares each combination of option IDs to these rules to determine how your child products should be built, depending on how you have configured the `build_rules`. It depends on your requirements how you configure your `build_rules`. #### Invalid Build Rules The `build_rules` are invalid if both the option IDs come from the same variation. Combinations of option IDs in the nested arrays must come from different variations. If Commerce cannot resolve the `build_rules` a `could not determine whether to include or exclude a child product due to ambiguous rules` error is returned. This error can occur, for example, if you have the same number of variation option IDs in both the `include` and `exclude` arrays and the variation option IDs match. ### Building Child Products Building child products is an asynchronous operation. When you build child products, a job is created. The jobId of the job is displayed in the response. When the job is complete, the build child products operation is also complete. You can use the jobId to see the status of your job using the `Get a Job` endpoint. Jobs are processed one at a time. You can continue to send build child product requests, but those jobs are queued. In other words, Commerce looks for any jobs that have a status of PENDING and starts the job with the earliest created date. This process is repeated until all jobs are processed. See Jobs. Re-building child products after adding or removing a new variation changes the total number of child products that you can generate from a parent product. When you rebuild the child products after updating variations associated with the parent product, all existing child products that belong to a parent product are deleted. New child products are created with new product IDs. If you have any bundles that reference child products directly, then you must update the bundles with the new child product IDs. However, re-building child products after adding or removing an option does not change the existing product IDs. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Bundle Component Products Relationships With Product Experience Manager, you can create and manage bundles. A bundle is a purchasable product, consisting of one or more products that you want to sell together. You can create multiple components within a bundle. Each component must have at least one or more options. Each option is a product and a quantity. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Cancel a Job(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; The jobs endpoints display the status of a number of endpoints that function as jobs, for example, product import and export, and duplicating hierarchies. Jobs are processed one at a time. You can continue to send job requests, but those jobs are queued. In other words, Commerce looks for any jobs that have a status of PENDING and starts the job with the earliest created date. If you decide that a specific job needs to be prioritized over another, you can cancel the less critical job using the `Cancel a job` endpoint. You can only cancel jobs whose status is PENDING. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a custom relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Custom relationships can either be bi-directional or uni-directional. - **Uni-Directional**: By setting `bi_directional` to `false` (or omitted from request) a uni-directional custom relationship will be created. Within a uni-directional relationship, if Product A links to Product B, Product B will not link back to Product A. This is ideal when one product (e.g., a base product) recommends another (e.g., an upsell), but the reverse recommendation is unnecessary. - **Bi-Directional**: By setting `bi_directional` to `true` a bi-directional custom relationship will be created. Within a bi-directional relationship, if Product A is linked to Product B, Product B will automatically link back to Product A. This bi-directionality ensures a consistent experience, where products always suggest each other as related items. For more information on use cases, see [Custom Relationships](/guides/key-concepts/product-experience-manager/custom-relationships/). Custom Relationship slugs must meet the following criteria: - be unique - be prefixed with `CRP_`. Product Experience Manager automatically adds the `CRP_` prefix if you do not include it. - contain A to Z, a to z, 0 to 9, hyphen, underscore, and period. Spaces or other special characters like ^, [], *, and $ are not allowed. Once a custom relationship has been created, you can then create Product Relationships: 1. Add the custom relationship to a product. See [Attach a custom relationship to a product](/docs/api/pxm/products/attach-custom-relationships). 2. Associate a product to multiple products. See [Associate a product with other products under a custom relationship](/docs/api/pxm/products/product-association-id). Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create relationships between a hierarchy and child nodes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to create relationships between a hierarchy and one or more child nodes. You can create a relationship only if: - All child nodes already exist. - Every child node in the request body must belong to this hierarchy. - All siblings in a hierarchy must have a unique `name` and `slug`. Siblings are the child nodes that are related to the same parent. ### Sort Order You can also provide `sort_order` information when you create a relationship by adding a `meta` object to the array of node reference objects for each child node that requires sorting. The node with the highest value of `sort_order` appears at the top of the response. For example, a node with a `sort_order` value of `3` appears before a node with a `sort_order` value of `2`. - If you don’t provide `sort_order` when creating relationships, all child nodes in the response for Get a Hierarchy’s Children request are ordered by the `updated_at` time in descending order. The most recently updated child node appears at the top of the response. - If you set `sort_order` for only a few child nodes or not all, the child nodes with `sort_order` value appear first in the response and then other child nodes appear in the order of `updated_at` time. You can also specify a `sort_order` when creating and updating a node. - If you create or update a node (**Node A**) with a `sort_order` and then you create a relationship for **Node A** with hierarchy (**Hierarchy A**) with a new `sort_order`, the `sort_order` you specified when creating\updating **Node A** is overwritten. - If you create\update **Node A** and then you create a relationship with **Hierarchy A** but do not configure a `sort_order`, the `sort_order` you specified when you created\updated **Node A** is not overwritten. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a hierarchy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; ```mdx-code-block import CASummary from '/docs/partials/pxm/custom-attributes/custom-attribute-spec-summary.mdx'; Creates a hierarchy with a name, description, and slug to organize products in your catalog. ``` Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a modifier(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can specify different modifiers for different options in a variation. When you build child products using options in variations, the properties of a child products depends on the modifier set for the options that are applied to the child product. The table below describes the different types of modifiers. | Modifier | Data Type | Effect | | :--- | :--- | :--- | | `name_equals` | `string` | Overrides the name of the child product with the name specified by the modifier. | | `name_append` | `string` | Appends the string specified in the modifier to the name of the child product. | | `name_prepend` | `string` | Prepends the string specified in the modifier to the name of the child product. | | `description_equals` | `string` | Overrides the description of the child product. | | `description_append` | `string` | Appends the string specified in the modifier to the description of the child product. | | `description_prepend` | `string` | Prepends the string specified in the modifier to the product description of the child product. | | `commodity_type` | `string` | Sets the commodity type of the child product, such as `physical` or `digital`. | | `price` | `string` | Allows application of price modifiers (`price_increment`, `price_decrement`, and `price_equals`) to the child products. | | `price_increment` | `string` | Increases the price of the child product. | | `price_decrement` | `string` | Decreases the price of the child product. | | `price_equals` | `string` | Sets the price of a child product to the amount you specify. | | `slug_append` | `string` | Appends the string specified in the modifier to the slug of the child product. Can only contain A-Z, a-z, 0 to 9, hyphen, underscore, and period. Spaces or other special characters like ^, [], *, and $ are not allowed. However, for the `slug-builder` modifier, you can use `{}` in the `seek` field, for example, `"seek": :{COLOR}"`. | | `slug_prepend` | `string` | Prepends the string specified in the modifier to the slug of the child product. Can only contain A-Z, a-z, 0 to 9, hyphen, underscore, and period. Spaces or other special characters like ^, [], *, and $ are not allowed. However, for the `slug-builder` modifier, you can use `{}` in the `seek` field, for example, `"seek": :{COLOR}"`. | | `slug_builder` | `string`| Sets a part of the slug of the child product. Can only contain A-Z, a-z, 0 to 9, hyphen, underscore, and period. Spaces or other special characters like ^, [], *, and $ are not allowed. However, for the `slug-builder` modifier, you can use `{}` in the `seek` field, for example, `"seek": :{COLOR}"`. | | `sku_equals` | `string` | Sets the SKU of the child product. | | `sku_append` | `string` | Appends the string specified in the modifier to the SKU of the child product. | | `sku_prepend` | `string` | Prepends the string specified in the modifier to the SKU of the child product. | | `sku_builder` | `string` | Sets a part of the SKU of the child product. | | `status` | `string` | Sets the status of the child product, such as `draft` or `live`. | Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create relationships between a node and child nodes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use this endpoint to create relationships between a single parent node and one or more child nodes. You can create a relationship only if: - The parent node already exists. - All child nodes already exist. - Every child node in the body of the request exists in the same hierarchy as the parent node. - A node is not a parent of itself. An array of child nodes request body must not contain the ID of the parent node in the path. - All siblings in a hierarchy must have a unique `slug`. Siblings are the child nodes that are related to the same parent. ### Sort Order You can also provide `sort_order` information when you create a relationship by adding a `meta` object to the array of node reference objects for each child node that requires sorting. The node with the highest value of `sort_order` appears at the top of the response. For example, a node with a `sort_order` value of `3` appears before a node with a `sort_order` value of `2`. - If you don’t provide `sort_order` when creating relationships, all child nodes in the response for Get a Node’s Children request are ordered by the `updated_at` time in descending order. The most recently updated child node appears at the top of the response. - If you set `sort_order` for only a few child nodes or not all, the child nodes with `sort_order` value appear first in the response and then other child nodes appear in the order of `updated_at` time. You can also specify a `sort_order` when creating and updating a node. - If you create or update a node (**Node A**) with a `sort_order` and then you create a relationship for **Node A** with another node (**Node B**) with a new `sort_order`, the `sort_order` you specified when creating\updating **Node A** is overwritten. - If you create\update **Node A** and then you create a relationship with **Node B** but do not configure a `sort_order`, the `sort_order` you specified when you created\updated **Node A** is not overwritten. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a node's product relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Creates relationships between the specified node and one or more products in a specified hierarchy. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a node import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; ```mdx-code-block import CASummary from '/docs/partials/pxm/custom-attributes/custom-attribute-spec-summary.mdx'; Creates a node in the specified hierarchy. ``` ### Sorting Nodes in a Hierarchy You can sort the order of your nodes, regardless of where the nodes are in the hierarchy. You can do this by adding a `meta` object to the body of your request and specifying a `sort_order` value. The node with the highest value of `sort_order` is displayed first. For example, a node with a `sort_order` value of `3` appears before a node with a `sort_order` value of `2`. - If you don’t provide `sort_order` when creating nodes, all child nodes in the response for Get a Node’s Children request are ordered by the `updated_at` time in descending order, with the most recently updated child node first. - If you set `sort_order` for only a few child nodes, the child nodes with a `sort_order` value appear first and then other child nodes appear in the order of `updated_at` time. You can also specify a `sort_order` when creating a node relationship. - If you create a node (**Node A**) with a `sort_order` and then you create a relationship for **Node A** with another node (**Node B**), the `sort_order` you specified when creating **Node A** is overwritten. - If you create **Node A** and then you create a relationship with **Node B** but do not configure a `sort_order`, the `sort_order` you specified when you created **Node A** is not overwritten. ### Curating Products in a Node You can curate the products in a node. Product curation allows you to promote specific products within each node of your hierarchies, enabling you to create unique product collections in your storefront. For example, you may find you have an abundance of cotton T-Shirts and you want to promote these products to the top of the product list. When a shopper navigates to T-shirts, the cotton T-Shirts are displayed first. You can do this by adding a `curated_products` attribute to the body of your request and adding an array of product IDs to the attribute. You should add the products IDs in the order you want them to be displayed in your node. The first product ID is displayed first in the product list. You can only curate 20 products or less. You cannot have more than 20 curated products. - The product IDs you provide must exist in the specified node. - If a curated product is removed from a node, the product is also removed from the curated_products list. - Once you have curated the products in a node, you can use the get node products endpoint to retrieve a list of curated products. You can then display your curated products in your catalogs using the following catalog endpoints. - Get a node in your latest catalog release. - Get a node in a catalog. - Get all nodes in your latest catalog release. - Get all nodes in a catalog. - Get node children in your latest catalog release. - Get node children in a catalog. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a product file relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a product file relationship Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create main image relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Associates a main image with the specified product. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a product template relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves all the templates that are associated with the specified product. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a product variation relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a product variation relationship Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a product or bundle import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Creates a product or bundle with the attributes that are defined in the body. #### Product Types Product Experience Manager automatically assigns types to the products you create. You can filter on product types. Product types can also be used in catalogs. For example, in your catalog, you can filter on `parent` so that only your parent products are displayed in your storefront. See [**Product Types**](/docs/api/pxm/products/products#product-types). #### Product Tags You can use product tags to store or assign a key word against a product or service that you sell in your store. The product tag can then be used to describe or label that product. Product tags represent similarities between products who do not share the same attributes. Using product tags means that you can group your products together, for example, by brand, category, subcategory, colors, types, industries, and so on. See [**Product Tags**](/docs/api/pxm/products/product-tags). #### Personalizing Products You can allow your shoppers to add custom text to a product when adding product items to their carts. This is useful, for example, if you have a product like a T-shirt that can be personalized, or you sell greetings cards that can be printed with your shoppers personalized messages. You can do this by configuring the `custom_inputs` attribute. When configuring the `custom_inputs` attribute: - You can rename `input` to something more representative of the input that shoppers are adding, for example, `message` or `front`. - `name` is the name that is displayed in your storefront. - You can add validation rules. For example, the input field must be a `string` and/or up to 255 characters in length. The limit is 255 characters. - You can specify if the input field is required. #### Curating Products You can curate the products in a node. Product curation allows you to promote specific products within each node of your hierarchies, enabling you to create unique product collections in your storefront. For example, you may find you have an abundance of cotton T-Shirts and you want to promote these products to the top of the product list. When a shopper navigates to T-shirts, the cotton T-Shirts are displayed first. See [**Update a node**](/docs/api/pxm/products/update-node). #### Bundles With Product Experience Manager, you can use the products API to create and manage bundles. A bundle is a purchasable product, consisting of one or more products that you want to sell together. See [**Bundles**](/docs/api/pxm/products/products#bundles). Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a variation option import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a variation option Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a variation import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a variation Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete a custom relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes the specified custom relationship. Custom Relationships cannot be deleted if they are in use. Request --- ## Delete a hierarchy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes the specified hierarchy and all its children. Request --- ## Delete a modifier(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You cannot delete a modifier if it is in use. Deleting a modifier in us returns a `422 Failed Validation` error. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete a node's parent import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a node's parent Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Deletes a node's product relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes a node's product relationships Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Deletes a node import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes a node by the node ID Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete a product file relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a product file relationships Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete Main Image Relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete Main Image Relationships Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete a product template relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a product template relationship Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete a product variation relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a product variation relationships Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete a product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes the specified product. You cannot delete a product if it is part of a bundle. You must first delete the bundle before you delete the product. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete a variation option import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a variation option Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete a variation and all it's associated options. import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a variation and all it's associated options. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete Custom Relationships from a Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete Custom Relationships from a Product. Multiple Custom Relationships can be deleted from a product in one request. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Detach multiple nodes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Dissociates products from multiple hierarchies and their children nodes. You can apply filters to search for the appropriate products to detach. For general filtering syntax, see [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | Example | | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `eq` | `id`, `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `name`, `templates`, `commodity_type`, `owner`, `product_types`, `parent_id`, `component_option_id`, `tags`, `status`, `has_nodes (false only)`, `created_at`, `updated_at`, `external_ref`, `description` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. For `product_types`, you can only specify one product type. **Note:** `has_nodes` can only be filtered as `false`. **Note:** `component_option_id` matches when a bundle includes that product id as a component option. | `?filter=eq(name,some-name)` | | `like` | `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `name`, `tags`, `description`, `external_ref` | Like. Checks if the operand contains the specified string. Wildcards are supported. | `?filter=like(name,*some-name*)` | | `in` | `id`, `name`, `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `product_types`, `parent_id`, `component_option_id`, `tags`, `external_ref` | Checks if the values are included in the specified list. If they are, the condition is true. For `product_types`, you can specify more than one product type. | `?filter=in(id,some-id)` | | `gt` | `id`, `created_at`, `updated_at`, `external_ref` | Greater than. Checks if the value of the field is greater than the given value. | `?filter=gt(updated_at,2024-01-01T00:00:00Z)` | | `ge` | `id`, `created_at`, `updated_at`, `external_ref` | Greater than or equal to. Checks if the value of the field is greater than or equal to the given value. | `?filter=ge(created_at,2023-01-01T00:00:00Z)` | | `lt` | `id`, `created_at`, `updated_at`, `external_ref` | Less than. Checks if the value of the field is less than the given value. | `?filter=lt(updated_at,2025-01-01T00:00:00Z)` | | `le` | `id`, `created_at`, `updated_at`, `external_ref` | Less than or equal to. Checks if the value of the field is less than or equal to the given value. | `?filter=le(created_at,2022-01-01T00:00:00Z)` | | `eq` (extensions) | `extensions.book.isbn` | Filters using a nested extension field. | `?filter=eq(extensions.book.isbn,1765426)` | | `eq` (shopper_attributes) | `shopper_attributes.color` | Filters using a shopper custom attribute field. | `?filter=eq(shopper_attributes.color,red)` | | `eq` (admin_attributes) | `admin_attributes.warehouse` | Filters using an admin custom attribute field. | `?filter=eq(admin_attributes.warehouse,US-EAST)` | Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Delete a Relationship between a product with one or more products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a Relationship between a product with one or more products Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Duplicate a hierarchy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Using this option, you can duplicate an existing hierarchy. This is useful because it enables you to quickly and easily create multiple hierarchies with the same node structure. When you duplicate a hierarchy, you can specify a new name and/or a new description and/or a new slug for the duplicated hierarchy. All other attributes will stay the same. Any nodes in the existing hierarchy are also replicated in the duplicated hierarchy. In addition, you can optionally use the `include_products` attribute to specify whether you want products associated with the nodes in an existing hierarchy to be associated with the nodes in the duplicated hierarchy. By default, product relationships in an existing hierarchy are not duplicated in a duplicate hierarchy. Duplicating a hierarchy is an asynchronous operation. When you duplicate a hierarchy, a job is created. The jobId of the job is displayed in the response. When the job is complete, the duplicate hierarchy operation is also complete. You can use the jobId to see the status of your job using Get a Job. Jobs are processed one at a time. You can continue to send duplicate hierarchy requests, but those jobs are queued. In other words, Commerce looks for any jobs that have a status of PENDING and starts the job with the earliest created date. This process is repeated until all jobs are processed. Once the job is complete, run: - Get all hierarchies to retrieve the HierarchyId of your duplicated hierarchy. - Get a hierarchy to retrieve the nodes and (if applicable) products associated with the duplicated hierarchy. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Export Products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; The Export API is available to make bulk updates to products in Product Experience Manager. You might also export products for your personal requirements. The Export API builds a CSV file containing the product entries. A CSV file can contain up to 50,000 product entries. If you have more than 50,000 product entries, then another CSV file is created and so on, until all your products are exported. The Job endpoint response specifies the location where the CSV file is stored. See [Characteristics of CSV Files](/docs/api/pxm/products/product-export#characteristics-of-exporting-products). ### Custom Attributes in Exported CSV Exported CSV files include custom attribute columns using the prefixes `shopper_attributes.` and `admin_attributes.` followed by the attribute key name. For example, a product with `admin_attributes: {cost_of_goods: "42.0"}` produces a column `admin_attributes.cost_of_goods` in the exported file. You can select specific attribute columns to include in the export using the `columns.include` parameter. You may specify individual keys (for example, `admin_attributes.cost_of_goods`) or use a wildcard to include all keys of a given type (for example, `admin_attributes.*`). You cannot combine a wildcard and individual keys for the same attribute type in a single export request. ### Exporting Selected Columns Product exports support the ability to select a subset of columns to be included in the generated .csv file. This allows you to export only the data you need, making it easier to work with smaller, more focused datasets. To specify the columns you want to include in the export, use the columns.include parameter in the request body of this endpoint. This parameter accepts an array of strings, where each string represents the name of a product attribute or a flow field. #### Specifying Flow Field Columns: The format for specifying flow field columns depends on the useTemplateSlugs setting: * useTemplateSlugs: `true`: Specify flow field columns using the format: `products():`. For example: `products(my_flow):my_field`. * useTemplateSlugs: `false` (default): Specify flow field columns using the format: `template::`. For example: `template:82c10a02-1851-4992-8ecb-d44f2782d09b:my_field`. #### Mandatory Fields: To ensure successful re-importing of product data, the following fields are always included in the export, regardless of the columns.include parameter: * id * name * sku * external_ref * commodity_type If the `columns.include` parameter is not provided in the request, the system will export all available product fields. ### Filtering The following attributes and operators are supported. | Operator | Attribute | Description | Example | | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `eq` | `id`, `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `name`, `templates`, `commodity_type`, `owner`, `product_types`, `parent_id`, `component_option_id`, `tags`, `status`, `has_nodes (false only)`, `created_at`, `updated_at`, `external_ref`, `description` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. For `product_types`, you can only specify one product type. **Note:** `has_nodes` can only be filtered as `false`. **Note:** `component_option_id` matches when a bundle includes that product id as a component option. | `?filter=eq(name,some-name)` | | `like` | `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `name`, `tags`, `description`, `external_ref` | Like. Checks if the operand contains the specified string. Wildcards are supported. | `?filter=like(name,*some-name*)` | | `in` | `id`, `name`, `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `product_types`, `parent_id`, `component_option_id`, `tags`, `external_ref` | Checks if the values are included in the specified list. If they are, the condition is true. For `product_types`, you can specify more than one product type. | `?filter=in(id,some-id)` | | `gt` | `id`, `created_at`, `updated_at`, `external_ref` | Greater than. Checks if the value of the field is greater than the given value. | `?filter=gt(updated_at,2024-01-01T00:00:00Z)` | | `ge` | `id`, `created_at`, `updated_at`, `external_ref` | Greater than or equal to. Checks if the value of the field is greater than or equal to the given value. | `?filter=ge(created_at,2023-01-01T00:00:00Z)` | | `lt` | `id`, `created_at`, `updated_at`, `external_ref` | Less than. Checks if the value of the field is less than the given value. | `?filter=lt(updated_at,2025-01-01T00:00:00Z)` | | `le` | `id`, `created_at`, `updated_at`, `external_ref` | Less than or equal to. Checks if the value of the field is less than or equal to the given value. | `?filter=le(created_at,2022-01-01T00:00:00Z)` | | `eq` (extensions) | `extensions.book.isbn` | Filters using a nested extension field. | `?filter=eq(extensions.book.isbn,1765426)` | | `eq` (shopper_attributes) | `shopper_attributes.color` | Filters using a shopper custom attribute field. | `?filter=eq(shopper_attributes.color,red)` | | `eq` (admin_attributes) | `admin_attributes.warehouse` | Filters using an admin custom attribute field. | `?filter=eq(admin_attributes.warehouse,US-EAST)` | Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Extending Products with Templates ```mdx-code-block import TemplatesOverview from '/docs/partials/pxm/templates/extendingproducts.mdx'; ``` ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Get a hierarchy's children(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a hierarchy's children #### Filtering Many Commerce API endpoints support filtering. The general syntax is described in [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | Example | |----------------|------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|------------------------------------------| | `eq` | `id`, `hierarchy_id`, `owner`, `parent_id`, `name`, `slug`, `description`, `has_children`, `created_at`, `updated_at`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.id`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Equals. Checks if the value of the attribute matches the specified value. | `filter=eq(name,some-name)`, `filter=eq(locales.fr-FR.name,Nom-du-produit)` | | `in` | `id`, `hierarchy_id`, `parent_id`, `breadcrumbs.id` | Checks if the value of the attribute is included in the specified list. | `filter=in(id,1,2,3,4)` | | `lt`, `le`, `gt`, `ge` | `id`, `hierarchy_id`, `parent_id`, `created_at`, `updated_at` | Comparison operators. `lt`: Less than, `le`: Less than or equal to, `gt`: Greater than, `ge`: Greater than or equal to. | `filter=lt(id,100)`, `filter=ge(created_at,2022-01-01)` | | `like` | `name`, `slug`, `description`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Like. Checks if the attribute contains the specified string (wildcards supported). | `filter=like(name,*some-name*)`, `filter=like(locales.es-ES.description,*descripción*)` | | `ilike` | `name`, `slug`, `description`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Case-insensitive like. Same as `like` but ignores case when matching. | `filter=ilike(name,*some-name*)` | Request --- ## Get All Jobs(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; The jobs endpoints displays the status of a number of endpoints that function as jobs, for example, product import and export, price book import, building child products, and duplicating hierarchies. can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get all modifiers import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get all modifiers Request --- ## Get a node's children(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the child nodes for a specified node. #### Filtering Many Commerce API endpoints support filtering. The general syntax is described in [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | Example | |----------------|------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|------------------------------------------| | `eq` | `id`, `hierarchy_id`, `owner`, `parent_id`, `name`, `slug`, `description`, `has_children`, `created_at`, `updated_at`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.id`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Equals. Checks if the value of the attribute matches the specified value. | `filter=eq(name,some-name)`, `filter=eq(locales.fr-FR.name,Nom-du-produit)` | | `in` | `id`, `hierarchy_id`, `parent_id`, `breadcrumbs.id` | Checks if the value of the attribute is included in the specified list. | `filter=in(id,1,2,3,4)` | | `lt`, `le`, `gt`, `ge` | `id`, `hierarchy_id`, `parent_id`, `created_at`, `updated_at` | Comparison operators. `lt`: Less than, `le`: Less than or equal to, `gt`: Greater than, `ge`: Greater than or equal to. | `filter=lt(id,100)`, `filter=ge(created_at,2022-01-01)` | | `like` | `name`, `slug`, `description`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Like. Checks if the attribute contains the specified string (wildcards supported). | `filter=like(name,*some-name*)`, `filter=like(locales.es-ES.description,*descripción*)` | | `ilike` | `name`, `slug`, `description`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Case-insensitive like. Same as `like` but ignores case when matching. | `filter=ilike(name,*some-name*)` | Request --- ## Get all nodes in a hierarchy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; A fully paginated view of all nodes in a hierarchy regardless of depth. #### Filtering Many Commerce API endpoints support filtering. The general syntax is described in [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | Example | |----------------|------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|------------------------------------------| | `eq` | `id`, `hierarchy_id`, `owner`, `parent_id`, `name`, `slug`, `description`, `has_children`, `created_at`, `updated_at`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.id`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Equals. Checks if the value of the attribute matches the specified value. | `filter=eq(name,some-name)`, `filter=eq(locales.fr-FR.name,Nom-du-produit)` | | `in` | `id`, `hierarchy_id`, `parent_id`, `breadcrumbs.id` | Checks if the value of the attribute is included in the specified list. | `filter=in(id,1,2,3,4)` | | `lt`, `le`, `gt`, `ge` | `id`, `hierarchy_id`, `parent_id`, `created_at`, `updated_at` | Comparison operators. `lt`: Less than, `le`: Less than or equal to, `gt`: Greater than, `ge`: Greater than or equal to. | `filter=lt(id,100)`, `filter=ge(created_at,2022-01-01)` | | `like` | `name`, `slug`, `description`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Like. Checks if the attribute contains the specified string (wildcards supported). | `filter=like(name,*some-name*)`, `filter=like(locales.es-ES.description,*descripción*)` | | `ilike` | `name`, `slug`, `description`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Case-insensitive like. Same as `like` but ignores case when matching. | `filter=ilike(name,*some-name*)` | Request --- ## List all nodes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; A fully paginated view of all nodes in all hierarchies regardless of depth. #### Filtering Many Commerce API endpoints support filtering. The general syntax is described in [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | Example | |----------------|------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|------------------------------------------| | `eq` | `id`, `hierarchy_id`, `owner`, `parent_id`, `name`, `slug`, `description`, `has_children`, `created_at`, `updated_at`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.id`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Equals. Checks if the value of the attribute matches the specified value. | `filter=eq(name,some-name)`, `filter=eq(locales.fr-FR.name,Nom-du-produit)` | | `in` | `id`, `hierarchy_id`, `parent_id`, `breadcrumbs.id` | Checks if the value of the attribute is included in the specified list. | `filter=in(id,1,2,3,4)` | | `lt`, `le`, `gt`, `ge` | `id`, `hierarchy_id`, `parent_id`, `created_at`, `updated_at` | Comparison operators. `lt`: Less than, `le`: Less than or equal to, `gt`: Greater than, `ge`: Greater than or equal to. | `filter=lt(id,100)`, `filter=ge(created_at,2022-01-01)` | | `like` | `name`, `slug`, `description`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Like. Checks if the attribute contains the specified string (wildcards supported). | `filter=like(name,*some-name*)`, `filter=like(locales.es-ES.description,*descripción*)` | | `ilike` | `name`, `slug`, `description`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Case-insensitive like. Same as `like` but ignores case when matching. | `filter=ilike(name,*some-name*)` | Request --- ## Get All Product Tags import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves all product tags for a store. A store can view the tags associated with the organization to which the store belongs. However, an organization can only view the tags associated with the organization. can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get all products(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all your products in the Product Experience Manager system. You can also use `include` to retrieve top-level resources, such as files or images, and key attribute data, such as SKU or slug for component products in a product bundle. With this option, you can get more information about the products in a product bundle in your store front, improving the buying experience for your shoppers. #### Pagination This endpoint supports offset-based pagination using `page[offset]` and `page[limit]` query parameters. :::caution Planned pagination changes — on or after 1 September 2026 The pagination links returned by this endpoint currently differ from the Elastic Path Commerce Cloud platform standard. Specifically, the `current` link is not returned, `first`/`last` are not always present, `prev` is incorrectly omitted on the second page, and `next` is incorrectly omitted on the second-to-last page. On or after **1 September 2026**, this endpoint will be updated so that `current` and `first` are always present, `last` is present on every page except the final page, `next` is present on every page except the last, and `prev` is present on every page except the first. See the [links](/docs/api/pxm/products/get-all-products#links) schema for full details. If your integration iterates through pages using these links, please verify that it will handle the updated behaviour correctly before this date. ::: #### Filtering Many Commerce API endpoints support filtering. The general syntax is described in [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | Example | | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `eq` | `id`, `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `name`, `templates`, `commodity_type`, `owner`, `product_types`, `parent_id`, `component_option_id`, `tags`, `status`, `has_nodes (false only)`, `created_at`, `updated_at`, `external_ref`, `description` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. For `product_types`, you can only specify one product type. **Note:** `has_nodes` can only be filtered as `false`. **Note:** `component_option_id` matches when a bundle includes that product id as a component option. | `?filter=eq(name,some-name)` | | `like` | `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `name`, `tags`, `description`, `external_ref` | Like. Checks if the operand contains the specified string. Wildcards are supported. | `?filter=like(name,*some-name*)` | | `in` | `id`, `name`, `sku`, `slug`, `upc_ean`, `manufacturer_part_num`, `product_types`, `parent_id`, `component_option_id`, `tags`, `external_ref` | Checks if the values are included in the specified list. If they are, the condition is true. For `product_types`, you can specify more than one product type. | `?filter=in(id,some-id)` | | `gt` | `id`, `created_at`, `updated_at`, `external_ref` | Greater than. Checks if the value of the field is greater than the given value. | `?filter=gt(updated_at,2024-01-01T00:00:00Z)` | | `ge` | `id`, `created_at`, `updated_at`, `external_ref` | Greater than or equal to. Checks if the value of the field is greater than or equal to the given value. | `?filter=ge(created_at,2023-01-01T00:00:00Z)` | | `lt` | `id`, `created_at`, `updated_at`, `external_ref` | Less than. Checks if the value of the field is less than the given value. | `?filter=lt(updated_at,2025-01-01T00:00:00Z)` | | `le` | `id`, `created_at`, `updated_at`, `external_ref` | Less than or equal to. Checks if the value of the field is less than or equal to the given value. | `?filter=le(created_at,2022-01-01T00:00:00Z)` | | `eq` (extensions) | `extensions.book.isbn` | Filters using a nested extension field. | `?filter=eq(extensions.book.isbn,1765426)` | | `eq` (shopper_attributes) | `shopper_attributes.color` | Filters using a shopper custom attribute field. | `?filter=eq(shopper_attributes.color,red)` | | `eq` (admin_attributes) | `admin_attributes.warehouse` | Filters using an admin custom attribute field. | `?filter=eq(admin_attributes.warehouse,US-EAST)` | Request --- ## Get all variation options import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get all variation options Request --- ## Get all variations import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get all variations Request --- ## Get child products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get child products Request --- ## Get a custom relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Gets a Custom Relationship. To see a list of custom relationships a product is attached to, see [Get all Custom Relationships attached to a Product](/docs/api/pxm/products/list-attached-custom-relationship). To see a list of products that a product is related to, see [Get all Related Products of a Products' attached Custom Relationship](/docs/api/pxm/products/get-related-products-of-a-product-id). Request --- ## Get all custom relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Gets all Custom Relationships. To see a list of custom relationships a product is attached to, see [Get all Custom Relationships attached to a Product](/docs/api/pxm/products/list-attached-custom-relationship). To see a list of products that a product is related to, see [Get all Related Products of a Products' attached Custom Relationship](/docs/api/pxm/products/get-related-products-of-a-product-id). ### Filtering Many Commerce API endpoints support filtering. The general syntax is described in [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | Example | | :--- |:---|:---|:---| | `eq` | `owner`, `slug` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | `filter=eq(owner,store)` | | `in` | `slug` | In. Checks if a value exists in a given list of values. If the value matches any item in the list, the condition is true. | `filter=in(slug,slug-1,slug-2,slug-3)` | Request --- ## Get a hierarchy(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the specified hierarchy. Request --- ## Get a node(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a node from a hierarchy. Request --- ## Get all hierarchies(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get all hierarchies #### Pagination This endpoint supports offset-based pagination using `page[offset]` and `page[limit]` query parameters. :::caution Planned pagination changes — on or after 1 September 2026 The pagination links returned by this endpoint currently differ from the Elastic Path Commerce Cloud platform standard. Specifically, the `current` link is not returned, `first`/`last` are not always present, `prev` is incorrectly omitted on the second page, and `next` is incorrectly omitted on the second-to-last page. On or after **1 September 2026**, this endpoint will be updated so that `current` and `first` are always present, `last` is present on every page except the final page, `next` is present on every page except the last, and `prev` is present on every page except the first. See the [links](#links) schema for full details. If your integration iterates through pages using these links, please verify that it will handle the updated behaviour correctly before this date. ::: #### Filtering Many Commerce API endpoints support filtering. The general syntax is described in [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | Example | |----------------|------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|------------------------------------------| | `eq` | `id`, `hierarchy_id`, `owner`, `parent_id`, `name`, `slug`, `description`, `has_children`, `created_at`, `updated_at`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.id`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Equals. Checks if the value of the attribute matches the specified value. | `filter=eq(name,some-name)`, `filter=eq(locales.fr-FR.name,Nom-du-produit)` | | `in` | `id`, `hierarchy_id`, `parent_id`, `breadcrumbs.id` | Checks if the value of the attribute is included in the specified list. | `filter=in(id,1,2,3,4)` | | `lt`, `le`, `gt`, `ge` | `id`, `hierarchy_id`, `parent_id`, `created_at`, `updated_at` | Comparison operators. `lt`: Less than, `le`: Less than or equal to, `gt`: Greater than, `ge`: Greater than or equal to. | `filter=lt(id,100)`, `filter=ge(created_at,2022-01-01)` | | `like` | `name`, `slug`, `description`, `locales.[locale].name`, `locales.[locale].description`, `breadcrumbs.name`, `breadcrumbs.slug`, `breadcrumbs.locales.[locale].name` | Like. Checks if the attribute contains the specified string (wildcards supported). | `filter=like(name,*some-name*)`, `filter=like(locales.es-ES.description,*descripción*)` | Request --- ## Get Job Errors import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get Job Errors Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get a Job(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a Job Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get a modifier(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a modifier Request --- ## Get a node's products(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the products associated with the specified hierarchy node from a published catalog. Products must be in a live status. If the products have been curated using the update a hierarchy node endpoint, then the products are returned in the order specified in the `curated_products` attribute in the body of the update a hierarchy node request. A product that is curated has the "curated_product": true attribute displayed. Request --- ## Get Bundle Component Product Relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves all the products included in the specified bundle product. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get all product file relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves all files that are associated with the specified product. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get Main Image Relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get Main Image Relationships Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get a Product Tag import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a product tag for a store. A store can view the tags associated with the organization to which the store belongs. However, an organization can only view the tags associated with the organization. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get all product template relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get all product template relationships Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get all product variation relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get all product variation relationships Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get a product(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns a product by its identifier. You can also use `include=component_products` to retrieve top-level resources, such as files or images, and key attribute data, such as SKU or slug for component products in a product bundle. With this option, you can get more information about the products in a product bundle in your store front, improving the buying experience for your shoppers. Request --- ## Get a product's nodes import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the nodes associated with the product. Products must be in a `live` status. Request --- ## Get all Related Product IDs of a Products' attached Custom Relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; ### Prerequisites - Relationships have been created between Products, see [Create a Relationship between a product with one or more products](/docs/api/pxm/products/product-association-id). Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get all Related Products of a Products' attached Custom Relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; ### Prerequisites - Relationships have been created between Products, see [Create a Relationship between a product with one or more products](/docs/api/pxm/products/product-association-id). Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Get a variation option import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a variation option Request --- ## Get a variation import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a variation Request --- ## Hierarchies ```mdx-code-block import HierarchyOverview from '/docs/partials/pxm/hierarchies/hierarchies.mdx'; import HierarchyCatalog from '/docs/partials/pxm/hierarchies/hierarchycatalogs.mdx'; ## Creating Hierarchies and Nodes You can create the **Major Appliances** hierarchy by performing the following steps. 1. Using [**Create a Hierarchy**](/docs/api/pxm/products/create-hierarchy), create a hierarchy whose name is **Major Appliances**. Each hierarchy has a hierarchy ID. In other words, the hierarchy ID is the ID of the root node. 1. Using [**Create a Node in a hierarchy**](/docs/api/pxm/products/create-node), create the following child nodes. When you create a node in a hierarchy, by default, the node is a child of the root node. Specify `sort_order` to configure the order of the nodes. - **Ranges** - **Refrigerators** - **Dishwashers** 1. Using [**Create a Node in a hierarchy**](/docs/api/pxm/products/create-node), create the **Electric Ranges** node, specifying **Ranges** as the parent node. 1. Using [**Create a Node in a hierarchy**](/docs/api/pxm/products/create-node), create the following nodes, specifying **Electric Ranges** as the parent node. - **Electric Ranges 24ˮ** - **Electric Ranges 30ˮ** - **Double Oven** 1. Using [**Create a Node in a hierarchy**](/docs/api/pxm/products/create-node), create the **Gas Ranges** node, specifying **Ranges** as the parent node. 1. Using [**Create a Node in a hierarchy**](/docs/api/pxm/products/create-node), create the following nodes, specifying **Gas Ranges** as the parent node. - **Gas Ranges 24ˮ** - **Gas Ranges 30ˮ** - **Gas Ranges 32"** - **Double Oven** 1. Using [**Create a Node in a hierarchy**](/docs/api/pxm/products/create-node), create the following nodes, specifying **Dishwashers** as the parent node. - **Built-in** - **Standalone** ## Hierarchies and Catalogs ``` ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Import Products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can use the Product Import API to: - Add new products, including: - main image files. See [Importing Main Image Files](/docs/api/pxm/products/product-import-bulk-update#using-imported-main-image-files). - custom data. See [Importing custom data](/docs/api/pxm/products/product-import-bulk-update#importing-custom-data-flows). - Make bulk updates to existing products. You cannot use product import to: - Delete existing products. - Import product bundles. The Product Import API uses a Comma Separated Values (CSV) file to import products, main image files, custom extension data, and admin and shopper attributes. Each row in a .csv file represents a product you want to create/update. See an [example file](/assets/pim_product_import_example.csv). Each file can have 50,000 rows, including the header. If a CSV file exceeds 50,000 rows, an error is displayed, and the products are not imported. A CSV file must not be larger than 50 megabytes. If a CSV file is larger than 50 megabytes, a `503 client read` error is displayed. If you want to create/update more than 50,000 products or your CSV file is larger than 50 megabytes, you must have a separate CSV file and import each CSV file one at a time. See [**Characteristics of CSV Files**](/docs/api/pxm/products/product-import-bulk-update#characteristics-of-csv-import-files). ## Custom Attributes in CSV You can set custom attributes on products using CSV columns with the prefixes `shopper_attributes.` or `admin_attributes.` followed by the attribute key name. For example: - `shopper_attributes.color` sets the `color` key on `shopper_attributes`. - `admin_attributes.cost_of_goods` sets the `cost_of_goods` key on `admin_attributes`. **Partial updates:** When updating an existing product, only the attribute keys present as columns in the CSV are affected. Attribute keys not included as columns are left unchanged. **Removing an attribute key:** To explicitly delete an attribute key from an existing product, set the cell value to `__REMOVE_ATTRIBUTE__`. This special sentinel value instructs the importer to remove that key from the product's custom attributes. An empty cell value is treated as a literal empty string, not a deletion. **New products:** For new products being created via import, any column whose value is `__REMOVE_ATTRIBUTE__` is ignored (the key is not created). Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Jobs(Products) ```mdx-code-block import ProductJobs from '/docs/partials/pxm/jobs/jobs.mdx'; ``` ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Get all Custom Relationships attached to a Product import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; ### Prerequisites - Custom Relationships have been attached to a product, see [Attach Custom Relationships to a Product](/docs/api/pxm/products/attach-custom-relationships) - **OR** Products have been related to one another, see [Create a Relationship between a product with one or more products](/docs/api/pxm/products/product-association-id) Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Create a Relationship between a Product with one or more Products import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; - You can associate a product with up to 2000 other products. - You do not need to attach a custom relationship to products beforehand, this will be done automatically by this endpoint. - This is a partial update, so if you make a request to this endpoint multiple times with different products in each request, they will not be overwritten but will be appended to the related products list. If you want to remove a relationship between products, see [Delete a Relationship between a product with one or more products](/docs/api/pxm/products/dissociate-products). ### Prerequisites - A Custom Relationship has been created, see [create a Custom Relationship](/docs/api/pxm/products/create-custom-relationship). - A Product has been created for the relationship to be based from. - One or many Product have been created for the product to relate to. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Product Experience Manager Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Product Experience Manager uses the PIM service to manage product information, hierarchies, and price books. Ideally, Product Experience Manager becomes the single source of truth for product data across your organization. In Commerce, the product data is stored separately from pricing, catalogs, and inventory. This separation means that you retrieve all product data only when you are managing product data and assets. Otherwise, when setting prices or managing inventory, you retrieve a reference to the product rather than the entire product, which makes the response times very fast. You also have the flexibility to create catalogs for different scenarios by combining hierarchies of products with a price book. Scenarios might include: - **Multiple geographical regions**. Display different catalogs in different regions with suitable pricing or combine product hierarchies from two different regions to display in a third region. - **Multiple channels**. Display different catalogs based on how a shopper accesses your store, such as through a mobile app or a web storefront. - **Direct to business versus direct to customers**. Offer different products and prices for business customers versus retail customers. - **Preferred customers**. Offer special pricing to preferred customers while displaying a standard price catalog to all other shoppers. - **Reward programs**. Enable reward programs where catalog prices drop after a certain spending level is reached. - **Product sales**. Offer sale items for a limited time. Scenarios are created by defining the context within which a catalog is displays. Contexts can be a customer ID, a channel, or any other user-defined tag that can be passed to the APIs from the front-end shopper experiences. Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Product Export ```mdx-code-block import ProductExport from '/docs/partials/pxm/import/export.mdx'; ``` ### Characteristics of Exporting Products - Product exports are an asynchronous operation. When you send a request to the Export API, it triggers an asynchronous job to build the `.csv` file containing the product entries. - Jobs are processed one at a time. You can continue to send product export requests, but those jobs are queued. In other words, Commerce looks for any jobs that have a status of PENDING and starts the job with the earliest created date. This process is repeated until all jobs are processed. See [**Jobs**](/docs/api/pxm/products/jobs). - The Export API response includes a job resource. In the response, you can verify the job status; if the status is successful, the response includes a link to the location where the `.csv` file is stored. See [**Product Export CSV File**](#product-export-csv-file). A single CSV file contains 10,000 rows, excluding the header. If you are exporting 50,000 products, the job endpoint response contains links to five `.csv` files; each `.csv` file including 10,000 products. - You might have specified custom extension data in a `.csv` file when you imported the products. These modifications are all exported. So, when you send a request to the Export API, the `.csv` file, included in the Job endpoint response, reflects any changes that you have made. - You cannot export product bundles. ### Product Export CSV File The Product Export API generates a Comma Separated Values (CSV) file that you can use to import/update products, main image files, and custom extension data. The `.csv` file is: - Comma-separated. - Header-based. - Header attributes must be the same as the product attributes. - Header names can be in any order. - Each row after the first line represents a single product. The following table describes the headers that are supported. | Header | Required | Description | |:---------------------------------|:---------|:-----------------------------------------------------| | id | Optional | A unique product ID that is generated when you create the product. The `id` is used to look up products in the `.csv` file and matches them to the products in your storefront that you want to update. | | external_ref | Optional | A unique attribute associated with a product. This could be an external reference from a separate company system, for example. The maximum length is 2048 characters. | | name | Required | The name of a product. | | description | Required | A description for a product. You can include quotes in your product description, if you want to emphasize a word, for example. To do this, put quotes around the product description. For example, "This product description describes my "product" and the product "version"." | | slug | Required | A label for the product that is used in the URL paths. A slug can contain any combination of letters, numbers, periods, hyphens, and underscores. NO spaces or other characters are allowed. By default, the product name is used as the slug. | | status | Required | The status of a product, either `Draft` or `Live`. | | commodity_type | Required | The commodity type, either `physical` or `digital`. | | upc_ean | Optional | The universal product code or european article number of the product. | | mpn | Optional | The manufacturer part number of a product. | | sku | Optional | The unique stock keeping unit of the product. | | tags | Optional | The product tags used to store or assign a key word against a product. A product can have up to 20 product tags. A product tag can be up to 255 characters. See [**Product Tags**](/docs/api/pxm/products/product-tags ). | | main_image_id | Optional | Specifies a unique ID of a main image file for a product. See [Exporting Main Image Files](#exporting-main-image-files). | | `_created_at` | Optional| The date and time a product was created. **Note**: This field does not populate any data; it is provided solely for informational purposes. | | `_updated_at` | Optional | The date and time a product was updated. **Note**: This field does not populate any data; it is provided solely for informational purposes. | | `template::created_at` | Optional | The date and time a template was created. **Note**: This field does not populate any data; it is provided solely for informational purposes. | | `template::updated_at` | Optional | The date and time a template was updated. **Note**: This field does not populate any data; it is provided solely for informational purposes. | | `template::` | Optional | Custom extension data includes the flow `ID` or `slug` and the field `name`. See [Exporting Custom Data (Flows)](#exporting-custom-data-flows). | ### Exporting Main Image Files The main images that you have previously uploaded Commerce are exported. A `main_image_id` header is added to your `.csv` file. The ID in `main_image_id` is the ID of a file that has already been uploaded to Commerce using [create a file](/docs/api/pxm/files/create-a-file). ### Exporting Custom Data (Flows) Custom extension data is exported in a `.csv` file by creating a header that includes the flow `ID` or `slug` and the field `name` as shown below: - `template::` - `template::` where: - `template` must be `template`. - one of the following for the template that contains the field whose data you want to export: - `flowID` is the ID of the flow. - `flowSlug` is the flow slug. - `fieldName` is the name of the field whose data you want to export. In the following example, for a flow with ID `82c10a02-1851-4992-8ecb-d44f2782d09b` and a field with the name `condition`: - the header is `template:82c10a02-1851-4992-8ecb-d44f2782d09b:condition`. - the updated custom data is `as-new`. | name | slug | sku | status | template:82c10a02-1851-4992-8ecb-d44f2782d09b:condition | | :--- | :--- | :--- | :--- | :--- | | BestEver Range | bestever-range-1a1a-30 | BE-Range-1a1a-30 | draft | as-new | ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Product File Relationships Products are the items or services that you might want to sell in your store. In Product Experience Manager, products can also have associated rich media assets, such as product images or a file containing additional product details. You can do this using [Files API](/docs/api/pxm/files). Once you have created your files, you associate files with your products using the [Create Product-File Relationships API](/docs/api/pxm/products/create-product-file-relationships). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Product Image Relationships Products are the items or services that you might want to sell in your store. In Product Experience Manager, products can also have associated rich media assets, such as product images or a file containing additional product details. You can do this using [Files API](/docs/api/pxm/files). Once you have created your files, you associate files with your products using the [Create Product Main Image Relationships API](/docs/api/pxm/products/create-product-main-image-relationships). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Product Import/Bulk Update ```mdx-code-block import ProductImport from '/docs/partials/pxm/import/import.mdx'; ``` #### Using Imported Main Image Files You can use the main images that you have previously uploaded to Commerce and assign them to your products when importing products to Commerce. You can do this by adding a `main_image_id` header to your `.csv` file. The ID you provide in `main_image_id` is the ID of a file that has already been uploaded to Commerce using create a file. #### Importing Custom Data (Flows) You can also create/update custom extension data in a `.csv` file by creating a header that includes the flow `ID` and the field `slug` in the following format: template:*flowID*:*fieldSlug*. where: - `template` must be `template`. - `flowID` is the ID of the flow that contains the field whose data you want to create/update. - `fieldSlug` is the slug of the field whose data you want to create/update. In the following example, for a flow with ID `82c10a02-1851-4992-8ecb-d44f2782d09b` and a field with the slug `condition`: - the header is `template:82c10a02-1851-4992-8ecb-d44f2782d09b:condition`. - the updated custom data is `as-new`. | name | slug | sku | status | template:82c10a02-1851-4992-8ecb-d44f2782d09b:condition | | :--- | :--- | :--- | :--- | :--- | | BestEver Range | bestever-range-1a1a-30 | BE-Range-1a1a-30 | draft | as-new | #### Characteristics of CSV Import Files Product Import uses a [**Comma Separated Values (CSV)**](#characteristics-of-csv-import-files) file to import/update products, main image files, and custom extension data. - Each row in a `.csv` file represents a product you want to create/update. - Each file: - must not be larger than 50 megabytes. If a `.csv` file is larger than 50 megabytes, a `503 client read error` is displayed. - must not have more than 50,000 rows, including the header. If a CSV file exceeds 50,000 rows, an error is displayed, and the products are not imported. In other words, if you have a file with 50,000 rows that is larger than 50 megabytes, an error is displayed, and the products are not imported. - If you want to create/update more than 50,000 products or your `.csv` file is larger than 50 megabytes, you must have a separate `.csv` file and import each `.csv` file one at a time. - You can update existing products, including images, templates/flow fields, and entries. The entry in the `.csv` file must have a unique `id` and/or `external_ref` that matches the `id` and `external_ref` of the existing product you want to update. You may have both a unique `id` and `external_ref`, but you must have at least one. - You can add new products. For new products that you want to add, the entry in the `.csv` file must have an `external_ref` that does not match any existing products. The following table describes the headers that are supported. | Header | Required | Description | |:---- |:---------|:--| | id | Optional | A unique product ID that is generated when you create the product. The `id` is used to look up products in the `.csv` file and matches them to the products in your storefront that you want to update. | | external_ref | Optional | A unique attribute associated with a product. This could be an external reference from a separate company system, for example. The maximum length is 2048 characters. | | name | Required | The name of a product. | | description | Required | A description for a product. You can include quotes in your product description, if you want to emphasize a word, for example. To do this, put quotes around the product description. For example, "This product description describes my "product" and the product "version"." | | slug | Required | A label for the product that is used in the URL paths. A slug can contain any combination of letters, numbers, periods, hyphens, and underscores. NO spaces or other characters are allowed. By default, the product name is used as the slug. | | status | Required | The status of a product, either `Draft` or `Live`. | | commodity_type | Required | The commodity type, either `physical` or `digital`. | | upc_ean | Optional | The universal product code or european article number of the product. | | mpn | Optional | The manufacturer part number of a product. | | sku | Optional | The unique stock keeping unit of the product. | | tags | Optional | The product tags used to store or assign a key word against a product. A product can have up to 20 product tags. A product tag can be up to 255 characters. See [**Product Tags**](/docs/api/pxm/products/product-tags). | main_image_id | Optional | Specifies a unique ID of a main image file for a product. You can include a `main_image_id` for your products for images that are already uploaded to Commerce. See [**Using Main Image Files**](#importing-custom-data-flows). | | `template::` | Optional | You can also specify custom extension data in the CSV by specifying the flow `ID` or `slug` and the field `name`. For example, `template::` format. See [**Importing Custom Data (Flows)**](#importing-custom-data-flows). | ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Product Tags ```mdx-code-block import ProductTags from '/docs/partials/pxm/products/tags.mdx'; ``` ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Products ```mdx-code-block import ProductsOverview from '/docs/partials/pxm/products/productsoverview.mdx'; import ProductTypes from '/docs/partials/pxm/products/types.mdx'; import ProductTags from '/docs/partials/pxm/products/tags.mdx'; import PersonalProducts from '/docs/partials/pxm/products/personalizing.mdx'; import ProductCatalogs from '/docs/partials/pxm/products/catalogs.mdx'; import Overview from "/docs/partials/pxm/bundles/bundles.mdx"; import ComponentOptions from "/docs/partials/pxm/bundles/components.mdx"; import BundlePricing from "/docs/partials/pxm/bundles/bundlepricing.mdx"; import DynamicBundles from "/docs/partials/pxm/bundles/dynamic.mdx"; import BundlesBundles from "/docs/partials/pxm/bundles/bundlesof.mdx"; ### Product Types ### Personalizing Products ### Products and Catalog Releases ### Bundles ### Bundle Components and Options ### Bundle Pricing ### Dynamic Bundles #### Creating Dynamic Bundles: An Overview The following steps are an overview of how to use dynamic bundles. 1. Create your products using [**create a product**](/docs/api/pxm/products/create-product). 1. Create a bundle using [**create a bundle**](/docs/api/pxm/products/create-product). 1. Specify minimum and/or maximum values for the number of product options that can be selected within the bundle. For example, if you want the shopper to select exactly 4 out of 10 options, set both the minimum and maximum values to 4 for each of the 10 product options. 1. For each product option in the bundle, specify if it is a default option by adding `"default": true` to the product options that you want to be pre-selected for the shopper. 1. Publish the bundle to your catalog using the [Publish a catalog](/docs/api/pxm/catalog/publish-release) endpoint so you can display the products to your shoppers in your storefront. 1. When a shopper interacts with the bundle on your storefront, they can select the products they want from the list of options. Use the [configure a shopper bundle](/docs/api/pxm/catalog/configure-by-context-product) endpoint to capture the shoppers selections. This updates the `bundle_configuration` with the product options chosen by a shopper. 1. Once a shopper has configured their bundle, use the add a product to a cart endpoint to add the selected bundle to the shopper’s cart. 1. When the shopper proceeds to checkout, the selected product options from the bundle are included in the order. ### Bundles of Bundles #### Creating Bundles of Bundles: An Overview To create a bundle of bundles, simply add a bundle as a component to another bundle. 1. Create your products using [**create a product**](/docs/api/pxm/products/create-product). 1. Create all your child bundles using [**create a bundle**](/docs/api/pxm/products/create-product). 1. [**Create a parent bundle**](/docs/api/pxm/products/create-product) and specify the product ID of your child bundle as an option of a component in your bundle. You cannot have more than 1500 options in a bundle. ``` ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Update a custom relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Updates a custom relationship. A partial update can be performed, where you specify only the fields that need to be changed. The custom relationship slug cannot be updated. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Update a hierarchy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; ```mdx-code-block import CASummary from '/docs/partials/pxm/custom-attributes/custom-attribute-spec-summary.mdx'; Updates a hierarchy. You can do a partial update, where you specify only the field value to change. ``` Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Update a modifier(Products) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the modifier is not updated. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Update a node's parent import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Changes the parent of the specified node. The new parent node must be located within the same hierarchy as the specified node. You cannot move a node to another hierarchy. If you want to put the specified node into another hierarchy, create the node in the target hierarchy and delete it from the current hierarchy. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Update a node import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; ```mdx-code-block import CASummary from '/docs/partials/pxm/custom-attributes/custom-attribute-spec-summary.mdx'; Updates the specified node in a hierarchy. You can do a partial update, where you specify only the field value to change. ``` ### Sorting Nodes in a Hierarchy You can sort the order of your nodes, regardless of where the nodes are in the hierarchy. The node with the highest value of sort_order is displayed first. For example, a node with a `sort_order` value of `3` appears before a node with a `sort_order` value of `2`. - If you don’t provide `sort_order` when creating nodes, all child nodes in the response for Get a Node’s Children request are ordered by the `updated_at` time in descending order, with the most recently updated child node first. - If you set `sort_order` for only a few child nodes or not all, the child nodes with a `sort_order` value appear first and then other child nodes appear in the order of `updated_at` time. You can also specify a sort_order when creating a node relationship. - If you update a node (**Node A**) with a `sort_order` and then you create a relationship for **Node A** with another node (**Node B**), the `sort_order` you specified when updating **Node A** is overwritten. - If you have updated **Node A** and then you create a relationship with **Node B** but do not configure a `sort_order`, the `sort_order` you specified when you updated **Node A** is not overwritten. ### Curating Products in a Node You can curate the products in a node. Product curation allows you to promote specific products within each node of your hierarchies, enabling you to create unique product collections in your storefront. For example, you may find you have an abundance of cotton T-Shirts and you want to promote these products to the top of the product list. When a shopper navigates to T-shirts, the cotton T-Shirts are displayed first. You can do this by adding a `curated_products` attribute to the body of your request and adding an array of product IDs to the attribute. You should add the products IDs in the order you want them to be displayed in your node. The first product ID is displayed first in the product list. You can only curate 20 products or less. You cannot have more than 20 curated products. - The product IDs you provide must exist in the specified node. - If a curated product is removed from a node, the product is also removed from the curated_products list. - Once you have curated the products in a node, you can use the get node products endpoint to retrieve a list of curated products. You can then display your curated products in your catalogs using the following catalog endpoints. - [Get a node in your latest catalog release](/docs/api/pxm/catalog/get-node) - [Get a node in a catalog](/docs/api/pxm/catalog/get-by-context-node) - [Get all nodes in your latest catalog release](/docs/api/pxm/catalog/get-all-nodes) - [Get all nodes in a catalog](/docs/api/pxm/catalog/get-by-context-all-nodes) - [Get node children in your latest catalog release](/docs/api/pxm/catalog/get-child-nodes) - [Get node children in a catalog](/docs/api/pxm/catalog/get-by-context-child-nodes) Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Replace a product file relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Replace a product file relationship Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Replace Main Image Relationships import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Replace Main Image Relationships Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Replace a product variation relationship import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Replace a product variation relationship Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Update a product or bundle import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the product or bundle is not updated. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Update a variation option import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a variation option Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Update a variation import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the variation is not updated. Request can not be empty"}]}}}}}},"500":{"description":"Internal server error. There was a system failure in the platform.","content":{"application/json":{"schema":{"required":["errors"],"properties":{"errors":{"type":"array","items":{"required":["status","title"],"properties":{"status":{"type":"string","description":"The HTTP response code of the error.","example":"500"},"title":{"type":"string","description":"A brief summary of the error.","example":"Internal server error"},"detail":{"type":"string","description":"Optional additional detail about the error.","example":"An internal error has occurred."},"request_id":{"type":"string","description":"Internal request ID.","example":"00000000-0000-0000-0000-000000000000"},"meta":{"type":"object","description":"Additional supporting meta data for the error.","example":{"missing_ids":["e7d50bd5-1833-43c0-9848-f9d325b08be8"]}}}}}},"title":"error"},"examples":{"internal-server-error":{"value":{"errors":[{"status":"500","title":"Internal Server Error","detail":"There was an internal server error, you can report with your request id.","request_id":"635da56d-75a1-43cd-b696-7ab119756b3a"}]}}}}}}}} > --- ## Variations ```mdx-code-block import VariationsOverview from '/docs/partials/pxm/variations/variationsoverview.mdx'; import VariationsReusability from '/docs/partials/pxm/variations/variationsreusability.mdx'; import ChildProducts from '/docs/partials/pxm/variations/childproducts.mdx'; import BuildChildren from '/docs/partials/pxm/variations/buildchildproducts.mdx'; import ProductModifiers from '/docs/partials/pxm/variations/productmodifiers.mdx'; import PriceModifiers from "/docs/partials/pxm/variations/pricemodifiers.mdx"; ### Reusability ### Child Products ### Building Child Products ### Sorting the Order of Variations and Options The `variation_matrix` object lists the variation IDs and variation option IDs and their corresponding product IDs that are generated when the variation and variation options are built with a product. The `variation_matrix` can then be added to your catalogs. The order of the variations in the `variation_matrix` is the order of the variations in the array when the variations were linked to the product. For example, the first variation in the `variation_matrix` corresponds to the first variation in the array, and so on. You can use the `sort_order`attribute to sort the order of your variation and variation options in the `variation_matrix` object. The sort order value is visible when you add the variations and variation options to your catalogs. You can then use the `sort_order` value to program your storefront to display the variations and variation options in the order that you want. Add the `sort_order` attribute to the body of your request and specify a `sort_order` value. A `sort_order` value must be a number. You can specify any numbers that you want. - 1, 2, 3, or 100, 90, 80, and so on. - Zero or negative numbers. You can set `sort_order` to either `null` or omit it entirely from the request if you wish to remove an existing `sort_order` attribute. :::caution - Commerce does not sort variations and variation options. You must program your storefront to sort the variations and variation options in the order that you want. - You must rebuild your products for the sort order changes to take effect. See [**Build Child Products**](#build-child-products). ::: ### Product Modifiers ### Price Modifiers ``` ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Delete Project Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes a store setting. Organization settings cannot be deleted. --- ## Get Project Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can get all of the project settings via one API call using a `client_credential` token. The response is in object format as shown in the following example. :::note The default `calculation_method` is `line`. ::: --- ## Update Project Settings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can use the Settings endpoint to update your project settings at any time. These global settings take immediate effect. Request --- ## Settings Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; The Settings API allow you to configure global settings for your project. You can define: - [page length when paginating results](/docs/api/settings/settings-introduction#page-length) - [the calculation method you want to use for cart and order totals](/docs/api/settings/settings-introduction#calculation-method) - [mandatory address fields](/docs/api/settings/settings-introduction#address-mandatory-fields) - [shopper address limit](/docs/api/settings/settings-introduction#shopper-address-limit) - [readonly store settings for internal stores](/docs/api/settings/settings-introduction#readonly-settings) ### Page Length This defines the number of results per page when paginating results (max: 100). | Name | Type | Default | Max | |--------------|-----------|--------- |-----| | `page_length` | `integer` | 25 | 100 | For more information on pagination including a list of which resources support pagination, see [Pagination](/guides/Getting-Started/pagination). ### Calculation Method This option defines the method used to calculate cart and order totals. Currently there are two methods: `simple` and `line`. The `simple` method is our previous method for calculating cart and order totals which focuses on the total value of the cart. This should only be used in the case where Composable Commerce is not used for tax calculations. The `line` method treats each line item individually resulting in more accurate figures after taxes and promotions are applied. | Name | Type | Value | |--------------|-----------|-------| | `calculation_method` | `string` | `line` | | `calculation_method` | `string` | `simple` | :::note - For stores created since February 2020, `line` is the default calculation method. Stores created before February 2020 use `simple` as their calculation method. - Line-item discount promotions, such as item percent discount and item fixed discount, are only supported by the line calculation method. For more information, see [Promotions Standard](/docs/api/promotions/promotions-standard-introduction). ::: ### Address Mandatory Fields You can create an address to associate with an account in your storefront. This defines the address fields that you can use when creating an address in Commerce Manager. For more information, see [Addresses](/docs/api/addresses/addresses-introduction). Address fields can be required or optional. You can choose which optional address fields to use in your address, depending on your requirements. To change which fields are mandatory for creating an address, see [Update Settings](/docs/api/settings/put-v-2-settings). Changing the mandatory fields does not impact the addresses of customers made before the change. The following table describes the address fields, their type and whether they are required by default. | Name | Type | Required | | :--- | :--- |:---------| | `type` |`string` | Default | | `first_name` |`string` | Default | | `last_name` |`string` | Default | | `name` |`string` | Optional | | `phone_number` |`string` | Optional | | `instructions` |`string` | Optional | | `company_name` |`string` | Optional | | `line_1` |`string` | Default | | `line_2` |`string` | Optional | | `city` |`string` | Optional | | `county` |`string` | Default | | `region` |`string` | Optional | | `postcode` |`string` | Default | | `country` |`string` | Default | ### Shopper Address Limit This defines the maximum number of addresses a shopper can create per resource (account). This helps prevent abuse and maintains database performance. | Name | Type | Default | Min | Max | |--------------|-----------|---------|-----|-------| | `shopper_address_limit` | `integer` | 25 | 1 | 25000 | :::note Only values up to 500 can be set by callers. Please [contact Support](https://support.elasticpath.com/hc/en-us#composable_commerce) if you require a higher limit. ::: ### Readonly Settings For internal store configurations, read-only settings are used and updating these settings fails without returning any error. :::note - Refer to the [Performance](/guides/Getting-Started/pagination#performance) section in the Pagination documentation, which outlines patterns for retrieving all documents without using a higher page offset limit. - To change any predefined configuration, contact [Elastic Path support team](https://support.elasticpath.com/hc/en-us). ::: | Name | Type | Default | |:------------------------|:----------|:-----------------------------------------------------| | `currency_limit` | `integer` | `10` | | `field_limit` | `integer` | `100` | | `integration_limit` | `integer` | `100` | | `event_limit` | `integer` | `5` | | `filter_limit` | `integer` | `10` | | `tax_item_limit` | `integer` | `5` | | `promotions_limit` | `integer` | `1000` | | `promotion_codes_limit` | `integer` | `1000` | | `page_offset_limit` | `integer` | `10000` | Security Scheme Type: http HTTP Authorization Scheme: bearer Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## Settings The Settings API allow you to configure global settings for your project. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Authentication Realms An authentication realm is a container that consists of the following: - Users - Represented by [User Authentication Info](/docs/api/single-sign-on/user-authentication-infos) objects - Authentication profiles - Ways for the users to authenticate, such as one or more [OpenID Connect Profiles](/docs/api/single-sign-on/oidc-profiles) or [Password Profiles](/docs/api/single-sign-on/password-profiles) - Mappings between users and authentication profiles - [User Authentication OpenID Connect Profile Info](/docs/api/single-sign-on/user-authentication-oidc-profile-infos) or [User Authentication Password Profile Infos](/docs/api/single-sign-on/user-authentication-password-profile-infos) Here's a domain diagram showing these relationships ![authentication realm](/assets/authentication-realm-domain.png) Composable Commerce comes with three per-store pre-set realms: - Buyer Organization. For customers: users who buy products from your store. - Merchant Organization. For administrators: users who log in to Commerce Manager to modify the store’s settings or catalog. - Account Management Realm. For account members: users who buy products from your store on behalf of accounts. Password profiles are only available for account management realm. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Delete OIDC Profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a specific OIDC profile by ID. Request --- ## Delete Password Profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete a specific password profile by ID. Request --- ## Delete User Authentication OIDC Profile Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete specific OIDC profile information by ID for a user. Request --- ## Delete User Authentication Password Profile Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete specific password profile information by ID for a user. Request --- ## Delete User Authentication Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete specific user authentication information by ID. Request --- ## Initiate OIDC Login import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Initiate the OIDC login flow for a specific store and authentication realm ::: note This is not an **API Endpoint**, but the [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) of the OpenID Connect Authentication Flow. To initiate an OpenID Connect authentication you must change the location in the Browser to this URL, not call it asynchronously. ::: Request --- ## OpenID Connect Discovery import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Returns the OpenID Connect discovery document for the authentication realm. This endpoint provides metadata about the OIDC provider's configuration, including endpoints, supported features, and capabilities. Some libraries might require an OIDC discovery document in order to work. For more information see [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html) Request --- ## Get OIDC Profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve a specific OIDC profile by ID. Request --- ## Get OIDC Profiles import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve OIDC profiles for the specified authentication realm. Request --- ## Get Password Profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve a specific password profile by ID. Request --- ## Get Password Profiles import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve password profiles for the specified authentication realm. Request --- ## Get User Authentication OIDC Profile Info by ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve specific OIDC profile information by ID for a user. Request --- ## Get User Authentication OIDC Profile Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve OIDC profile information for a specific user authentication info. Request --- ## Get User Authentication Password Profile Info by ID import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve specific password profile information by ID for a user. Request --- ## Get User Authentication Password Profile Info List import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve a list of password profile information for a user. Request --- ## Get User Authentication Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve specific user authentication information by ID. Request --- ## Get User Authentication Info List import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve user authentication information for the specified authentication realm. ### Filtering The following operators and attributes are available for [filtering](/guides/Getting-Started/filtering) unassigned account members. | Operator | Description | | :------- |:--------------------------------------------------------------------------------------------------- | | `eq` | Matches record where the field matches the value (case insensitive) | | `ge` | Matches results where the value is greater than or equal to the operand | | `gt` | Matches results where the value is greater than the operand | | `le` | Matches results where the value is less than or equal to the operand | | `lt` | Matches results where the value is less than the operand | | `in` | Matches results where the value is in one of a set of values | | `ilike` | Checks whether the operand contains the specified string. You can use wildcard characters at the start or end. (Case Insensitive) | | `is_null` | Matches records where the field is null. | | Attribute | Type | Operator | Example | :-------- | :------- | :------------ | :--------------------------------- | | `email` | `string` | `eq`,`ilike` | `eq(email,ronswanson@example.com)` | | `name` | `string` | `eq`,`ilike` | `ilike(name,*swan*)` | | `created_at` | `string` | `lt`, `le`, `eq`, `gt`, `ge` | `lt(created_at,"2025-09-10T22:08:47.992Z")` | | `updated_at` | `string` | `lt`, `le`, `eq`, `gt`, `ge` | `gt(updated_at,"2025-09-10T22:08:47.992Z")` | | `given_name` | `string` | `eq`,`ilike`,`is_null` | `is_null('given_name')` | | `middle_name` | `string` | `eq`,`ilike`,`is_null` | `is_null('middle_name')` | | `family_name` | `string` | `eq`,`ilike`,`is_null` | `is_null('family_name')` | Request --- ## Get an Authentication Realm import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve a specific authentication realm by its ID. Request --- ## Get all Authentication Realms import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieve a list of all authentication realms configured for your store. Authentication Realms allow you to configure authentication options and manage single sign-on settings. Each realm contains users, authentication profiles, and mappings between users and authentication profiles. Request --- ## OIDC Authentication The OIDC IDP Login endpoints handle the initiation of OpenID Connect authentication flows. When a user needs to authenticate via OIDC, they are redirected to these endpoints which then redirect them to the configured OIDC provider for authentication. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## OIDC Profiles An OpenID Connect Profile resource represents a specific configuration of an OpenID Connect Provider. An authentication realm can have multiple OpenID Connect Profiles. This allows shoppers to authenticate using multiple OpenID providers. In the example shown below, Jane can login using both Apple and Google, whereas Joan can only login using Google. ![oidc profiles](/assets/oidc-profiles.png) ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Password Profiles A `password_profile` resource represents a specific configuration that allows users to authenticate through username and password. Password Profiles support One-Time Password Tokens, which can be used to use passwordless login or password reset. An authentication realm can have multiple Password Profiles. You can use this flexibility in many ways. For instance, if you want to migrate an existing pool of users from another system with their own usernames and passwords, they can use one profile, while the rest of the users use another. Another use case is enabling shopper impersonation, where shoppers can authenticate using their own username and password in one profile. Meanwhile, admins can have a different username and password for the same user in a separate profile, shown as the "Impersonation Profile". This process can be automated using a Backend-For-Frontend (BFE) or One-Time Password Tokens. In the example shown below, both John and Joan can log in with their credentials, and an admin can also log in as Joan using the "Impersonation Profile". ![password profiles](/assets/password-profiles.png) ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Create an OIDC Profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create an OpenID Connect profile for the specified authentication realm. Request --- ## Create One-Time Password Token Request import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a one-time password token request for the specified password profile. Request --- ## Create Password Profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a password profile for the specified authentication realm. Request --- ## Create User Authentication OIDC Profile Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create OIDC profile information for a specific user authentication info. Request --- ## Create User Authentication Password Profile Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create password profile information for a specific user authentication info. Request --- ## Create User Authentication Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create user authentication information for the specified authentication realm. Request --- ## Update OIDC Profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a specific OIDC profile by ID. Request --- ## Update Password Profile import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a specific password profile by ID. Request --- ## Update User Authentication OIDC Profile Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update specific OIDC profile information by ID for a user. Request --- ## Update User Authentication Password Profile Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update specific password profile information by ID for a user. Request --- ## Update User Authentication Info import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update specific user authentication information by ID. Request --- ## Update an Authentication Realm import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a specific authentication realm by its ID. Request --- ## Single Sign On API import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Single sign-on allows authentication with Commerce using an external authentication provider. Using an existing authentication provider allows for integration with company-specific or customizable authentication systems. In some cases, it can also simplify the log-in experience because they don’t need to remember another password. Commerce supports two types of single sign-on users: - End users, that is, customers of your store. - Administrators, who can use single sign-on to log on to Commerce Manager. When users need to authenticate, they are redirected to the single sign-on provider, which then communicates the result of the authentication process back to Commerce. You can set up Commerce to allow single sign-on for end users, using the *OpenID Connect* standard. :::note When users authenticate using an external authentication provider, authentication details, such as username and password, are neither stored on nor sent through Commerce. ::: ## Authentication Providers and Composable Commerce Commerce supports many OpenID Connect compatible authentication providers. For more information, see [Requirements for Authentication Providers](/guides/How-To/Authentication/get-single-sign-on-account-management-token#requirements-for-authentication-providers). ## External Reference - [What is OpenID?](https://openid.net/foundation/) - [OpenID Connect Core](https://openid.net/specs/openid-connect-core-1_0.html) ## Related Resources - [Security](/docs/authentication/security) Security Scheme Type: http HTTP Authorization Scheme: bearer Bearer format: JWT Contact Elastic Path: [support@elasticpath.com](mailto:support@elasticpath.com) URL: [https://www.elasticpath.com](https://www.elasticpath.com) License MIT --- ## User Authentication Infos A `user-authentication-info` represents a user. This object contains information, such as the name and email address, and has sub-resources for each mechanism that the user can use to log in./single-sign-on/authentication-realm-api/authentication-realm-api-overview) and the user is configured to authenticate through that profile, then the `user-authentication-info` object is associated with a [User Authentication OpenID Connect Profile Info](/docs/api/single-sign-on/user-authentication-oidc-profile-infos) subresource. [Account Members](/docs/api/accounts/get-v-2-account-members-account-member-id) reference User Authentication Infos directly (i.e., for every account member there is an user authentication info with the same id) and the User Authentication Info API is how you manage and configure the authentication options for that user. [Customers (that login via OIDC)](/docs/customer-management/customer-management-api/get-a-customer) also use the User Authentication Info. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## User Authentication OIDC Profile Infos The `user-authentication-oidc-profile-info` object is the information object about the relationship between a [User Authentication Info](/docs/api/single-sign-on/user-authentication-infos) and an [OpenID Connect Profile](/docs/api/single-sign-on/oidc-profiles). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## User Authentication Password Profile Infos The `user-authentication-password-profile-info` object is the information object about the relationship between a [User Authentication Info](/docs/api/single-sign-on/user-authentication-infos) and a [Password Profile](/docs/api/single-sign-on/password-profiles) object. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Adds an offering's pricing options to the plan import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use the unique identifier of the pricing in the offering that you want to update. Any modifications that you make to the plans in an offering, does not affect any active subscriptions. The changes take effect on all new subscriptions that are created. Request --- ## Attach a feature import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; After saving an offering, you can attach new features to it at any time. Adding new features does not affect any existing active subscriptions. The changes take effect on all new subscriptions that are created. Request --- ## Build an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; An offering includes plans and pricing options; plans are combined with one or more pricing options to form an offering. An offering can include either: - subscription plans (created within an offering). - Product Experience Manager products. See [**create a product**](/docs/api/pxm/products/create-product). When you are building an offering: - you can create new pricing options and plans. - you can modify an existing plan and pricing options. For example, you can modify the plan price or any attributes of a pricing option included in the offering. Here's how you build an offering: 1. Specify the plan to build with the offering. A plan can be: - subscription plans. Specify the subscription plan attributes. - Product Experience Manager products. Specify the Product Experience Manager product ID in `external_ref` in `PlanAttributes`. For the remaining plan attributes, you can specify their values to match the values of the existing Product Experience Manager product attributes. However, you can also specify different values, depending on your requirements. 2. Specify the pricing options to build with the offering. Pricing options are the rules that govern your subscription, for example, any discount. You can combine and reuse pricing options for as many plans as you want, making it quick and easy to create your subscription offerings. An offering must have at least one pricing option. Request --- ## Create a dunning rule import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Dunning rules must use a `fixed` strategy. This means payments are retried on a fixed schedule. When an invoice is created, it immediately becomes eligible for payment by the next payment run. If the first payment attempt fails then the invoice enters dunning. In subsequent payment runs, invoices are only considered for payment if they meet the dunning rules you create. You can configure a dunning rule to be the default for your store. There can only be one default rule per store. All invoices in your store will then perform dunning according to the specified rules. :::note If no dunning rule is configured, then payment is retried once a day for 10 days, in total 11 payments. You can decide what action to take after the Subscriptions has stopped retrying the payments. ::: The following attributes are used to define a `fixed` schedule: - `payment_retry_unit - the unit of time used to measure the intervals between payment attempts or retries. - `payment_retry_interval` - the number of `payment_interval-units` to wait between each payment retry attempt. - `payment_retries_limit` - the number of times subscriptions attempts payments retries before an `action` is taken. - `action` - the action to take if payment is not successful. For example, if: - the `payment_retry_unit` is `days` - the `payment_retry_interval` is `2` - the `payment_rety_limit` is `10` - the `action` is `close`. Subscriptions attempts to retry the payment every 2 days until 10 payment attempts have been tried. At that point, the subscription ends and it's status changes to `inacive`. Following on from this, you can specify that the dunning rule is no longer the default. You do not have to specify another rule to replace it. If you do remove the default dunning rule, the store defaults to the behavior that is followed when dunning is not enabled. Request --- ## Create a feature import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a feature Request --- ## Import a dataset(Subscriptions) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Import a dataset Request --- ## Create a refund for an invoice payment import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Creates a refund for a paid invoice. Request --- ## Create a job import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a job Request --- ## Create a feature directly inside an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; After saving an offering, you can add new features to it at any time. Request --- ## Create a plan inside an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; After saving an offering, you can add new plans to it at any time. Request --- ## Create a pricing option inside an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; After saving an offering, you can add new pricing option to it at any time. Request --- ## Create an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create an offering Request --- ## Create a Proration Policy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; In Subscriptions, you configure proration by creating a proration policy and attaching it to an offering. Once you have [attached](/docs/api/subscriptions/update-offering) the policy, the proration policy applies to all subscriptions that use the offering. Request --- ## Create a schedule import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a schedule Request --- ## Create a subscriber import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a subscriber Request --- ## Create a subscription state import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; The subscription lifecycle is the states that a subscription can go through when a customer subscribes to a service or a plan. A subscription can have the following states: - `pending` - `canceled` - `paused` - `resumed` For more information, see [Managing the Subscription Lifecycle](/docs/api/subscriptions/subscriptions#managing-the-subscription-lifecycle). Immediate cancellation (`cancel` with `cancel_immediately: true`) ends the subscription and updates entitlements in this request; it does **not** issue refunds or modify paid invoices. Use payments refund flows separately if needed. Request --- ## Create a subscription import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Create a subscription Request --- ## Delete dunning rules import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can delete a dunning rule at any time. If a dunning rule is deleted then Subscriptions reverts to the configuration used if no dunning rule is set; payment is retried once a day for 10 days, in total 11 payments. You can decide what action to take after the Subscriptions has stopped retrying the payments. See [Dunning Rules](/docs/api/subscriptions/dunning-rules). Request --- ## Delete feature import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Remove a feature. Request --- ## Delete job import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete job Request --- ## Remove a feature from an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; After saving an offering, you can remove features from it at any time. Removing a feature from an offering does not affect any existing active subscriptions. The changes take effect on all new subscriptions that are created. Request --- ## Remove a plan from an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; After saving an offering, you can remove plans from it at any time. Removing a plan from an offering does not affect any existing active subscriptions. The changes take effect on all new subscriptions that are created. Request --- ## Remove a pricing option from an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; After saving an offering, you can remove pricing options from it at any time. Removing a pricing option from an offering does not affect any existing active subscriptions. The changes take effect on all new subscriptions that are created. Request --- ## Delete offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; When a subscription is created, it creates a snapshot of the offering. This means you can delete an offering without affecting any active subscriptions. Request --- ## Delete proration policy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; A proration policy cannot be deleted if it is being used by any subscriptions. This means you must detach a proration policy that you want to delete from any offerings using that policy before deleting the policy. See [Remove a proration policy from an offering](/docs/api/subscriptions/update-offering). Request --- ## Delete schedule import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete schedule Request --- ## Delete subscriber import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Delete subscriber Request --- ## Delete a subscription import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Deletes a subscription Request --- ## Dunning Rules Dunning is the process of handling failed payment attempts. This is important for recovering revenue from failed payments, reduces customer churn and maintains cashflow. By implementing efficient dunning processes, you can enhance financial health and operational efficiency. Subscriptions enables you to create a dunning rule that allows you to configure payment retry schedules. Subscriptions retries failed payments automatically. You can customize the timing and frequency of the payment retries. Dunning is enabled by default. You can choose to disable dunning. If no dunning rule is configured, then payment is retried once a day for 10 days, in total 11 payments. You can decide what action to take after the Subscriptions has stopped retrying the payments. - Do nothing - the subscription remains active and Subscriptions does not attempt to retry the payment. However, the subscription is still available for a subscriber to use. - Suspend the subscription. Subscriptions does not attempt to retry the payment. A subscriber can choose to pay the outstanding invoice. However, a subscriber cannot renew their subscription; a merchandizer must renew the subscription on behalf of the subscriber. - close a subscription. The subscription ends and it's status becomes `inactive`. However, a merchandizer can choose to resume the subscription if a subscriber pays the outstanding payment. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Features A feature indicates some benefit that is received as a result of having an active subscription. This translates to tags being applied to the subscriber's account allowing access to some resource to be controlled. There are three types of feature - `access`, `promotion`, and `usage`. The `access` feature is designed to simply give access to some resource, for example a streaming service. If its tag is present on the subscriber's account then access to that resource should be provided. The `promotion` feature coupled with the [promotions service](/docs/promotions-builder/overview) allows subscribers to get access to a specific promotion. This is achieved using a tag which is used as a constraint on the promotion. A promotion feature may have multiple promotions associated with it, but just one must be selected when configuring the feature for an offering's plan. The `usage` feature is designed to measure some sort of usage of a resource. This currently relies on [commerce extensions](/docs/api/commerce-extensions/commerce-extensions-introduction) to manage usage. Once defined a feature may be attached to an offering, making it available for use with any of that offering's plans. Once attached it must be configured for each of the offering's plans it is applicable to. For the `promotion` feature this involves specifying which of that feature's tags, and hence which promotion, should be applied when subscribed to that offering. Similarly, for the `promotion` feature the default value for the usage metric must be supplied. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Get dunning rule policy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get dunning rule policy Request --- ## Get feature import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get feature Request --- ## Get import errors(Subscriptions) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves all errors encountered as part of the import. Each error is attributed to a line in the JSONL file imported, so for example, if at line 1 in your JSONL you had a subscription_offering without a name, there would be a minimum string error for the `name` attribute with `"line_number": 1`. Errors are also ordered by line number ascending, and can be paginated. Request --- ## Get import(Subscriptions) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves the import job for the specified ID. Request --- ## Get a refund for an invoice payment import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a refund for a paid invoice. Request --- ## Get invoice payment import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get invoice payment Request --- ## Get invoice import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get invoice Request --- ## Get job import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get job Request --- ## Get a feature in an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a feature in an offering Request --- ## Get a plan in an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a plan in an offering Request --- ## Get a pricing option in an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a pricing option in an offering Request --- ## Get offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get offering Request --- ## Get proration policy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get proration policy Request --- ## Get a schedule import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a schedule Request --- ## Get a subscriber import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a subscriber Request --- ## Get a feature in a subscription import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a feature in a subscription Request --- ## Get subscription invoice payment import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Gets a specific payment for a given invoice. Request --- ## Get subscription invoice import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Gets a specific invoice for a given subscription. Request --- ## Get a plan in a subscription import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a plan in a subscription Request --- ## Get a pricing option in a subscription import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get a pricing option in a subscription Request --- ## Get subscription state import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get subscription state Request --- ## Get subscription import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Get subscription Request --- ## Imports(Subscriptions) You can import subscription features, subscribers, offerings and subscriptions using Subscriptions Import. This is useful if you want to import subscriptions from an external system into Elastic Path Subscriptions. The API uses a [**JSONL**](https://jsonlines.org/) file. Here is an [**example of a JSONL file**](/assets/subscriptions_import.jsonl). When you send an import request, an import job is created. Jobs are processed one at a time. You can continue to send import requests, but those jobs are queued. In other words, Subscriptions looks for any jobs that have a status of PENDING and starts the job with the earliest created date. This process is repeated until all jobs are processed. Use [List import jobs](/docs/api/subscriptions/list-import-jobs) to see a list of all import jobs. A file can include up to 50,000 objects. If you have more than 50,000 objects, then you must create a separate file, and import each file, one at a time. ### Characteristics of Subscriptions Import The Subscriptions Import API has the following characteristics: - The Subscriptions Import API reads the entire file and then creates the subscription objects. This means the subscription objects can be in any order in the file. - Subscriptions imports are asynchronous and are processed one at a time. You can continue to send import requests, but these are queued. - The API works on a "best endeavours" approach. In other words, the API does its best to create the subscription objects based on the file that you provide. ### Subscriptions Import File The following table describes the subscriptions objects, and their attributes, that the import file can include. | Object | Attributes | | --- | --- | | A subscriber object | The attributes you specify for a subscriber object are the attributes you specify when [creating a subscriber](/docs/api/subscriptions/create-subscriber). | | An offering object | The attributes you specify for an offering object are the attributes you specify when [building an offering](/docs/api/subscriptions/build-offering). | ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Invoices Invoices represent the amount a customer owes for a subscription. Elastic Path Subscriptions generates an invoice for every period in a subscription billing cycle. Invoices provide: - an itemized list of goods and services provided by a subscription. - the cost of a subscription. - if applicable, any taxes. The invoice lifecycle is described below. 1. When a subscription is created, an invoice for the first billing period is created. When a subscription is created as part of an order, the payment for the order covers the first billing period. 2. Subscription invoices are created by [**billing runs**](/docs/api/subscriptions/jobs). The billing run identifies subscriptions that require a new invoice for their next billing period and creates them. At this point, invoices are marked as outstanding. 3. Invoices where `tax_required` is `true` will not have payment taken until a tax run has added the required tax to the invoice. 3. The [**payment run**](/docs/api/subscriptions/jobs) identifies invoices that are still outstanding and attempts to take payment for them. If the payment succeeds the the invoice is no longer outstanding. If the payment fails for any reason, then the invoice remains outstanding and is picked up by the next payment run to retry the payment. If an invoice has a failed payment, payment is only retried if the fixed interval has passed from the last payment attempt as defined in Settings. ### Payment Retries It is important to limit the number of times Subscriptions retries a failed payment request for many reasons, including: frequent payment retries can indicate fraudulent activities; multiple failed payment attempts can lead to customers accounts being locked out or flagged for suspicious activity resulting in poor customer experience; and excessive retries places an unnecessary load on your payment processing system. In Subscriptions, by default, the number of payment retries is 10. You can set this to a limit between 0 - 20, depending on your requirements. Each payment retry is made as a payment run. Once the number of payment retries reaches the limit, the payment retries stop, resulting in status of the invoice being unpaid. See [Invoices](#invoices). When configuring payment retries, you have the following options. | Attribute | Required | Description | | --- | --- | --- | | `payment_retry_type` | Optional | One of the following options: `fixed` - use `fixed` if you want a fixed time interval between payment retries.`backoff` - use `backoff` if you want the time between retry attempts to increase exponentially.`tiered` - use `tiered` if you want to specify a list of time durations. | | `payment_retry_interval` | Optional | Represents the retry interval. For example, if `payment_retry_unit` is `week` and `payment_retry_interval` is `1` then, the payment retry interval is 1 week. | | `payment_retry_multiplier` | Optional | Use when `payment_retry_type` is `tiered` and represents the factor by which the time duration increases after each retry. | | `payment_retry_unit` | Optional | Represents the unit of time, either `day` or `week`. | ### Rounding Subscriptions always rounds down to the penny. ### Tax Subscriptions allows you to apply any number of tax rates to your invoices and subscriptions. When applying a tax rate, you must specify: - a name that appears on your customer's invoice that describes the specific type of tax. - the tax rate which is the percentage of the subscription amount that is required to be paid as tax. In addition, you can optionally specify the jurisdiction which is the geographic area or political entity that has authority to levey and collect taxes. You can apply more than one tax rate for all items in an invoice. You cannot apply a tax rate per line item. ### Payments When your customers add a subscription to a cart and the cart is checked out, an unpaid order is returned. You can process the payment for the order though a payment gateway. You can do this using: - Elastic Path Payments Powered by Stripe. The Elastic Path Payments Powered by Stripe gateway interacts with Stripe to allow your subscribers to pay for their subscriptions. - Authorize.Net. #### Using Elastic Path Payments Powered by Stripe To use Elastic Path Payments Powered by Stripe gateway, contact the [**Customer Success Team**](mailto:customersuccess@elasticpath.com). Create your Stripe account in [**Stripe Dashboard**](https://dashboard.stripe.com/login) and complete an onboarding form to make payments using the gateway. For more information, see [**Onboarding**](/docs/payments/onboarding). Once you have signed up for Elastic Path Payments Powered by Stripe, you must configure the payment gateway so that your shoppers can make payments. See [**Configure Elastic Path Payments Powered by Stripe**](/docs/payments/onboarding). #### Using Authorize.Net To use Authorize.Net, you must have: - an active merchant account with Authorize.Net - obtained API credentials. These include an **API Login ID** and a **Transaction Key**. - Enabled Authorize.Net in Commerce Manager. See [Enabling Authorize.net](/docs/commerce-manager/payments/configure-other-payment-gateways#enabling-authorizenet). #### Payment Requests Subscriptions only supports the `purchase` payment mechanism. The gateway attempts to charge the customer immediately, and the result of the attempt is returned. If a payment fails, the invoice is kept as outstanding and the payment information, with the reason for the failure is attached to the invoice. A new payment run is required to attempt another payment. When sending a payment request to the Payments service, you must specify the following. | Attribute | Required | Description | | --- | --- | --- | | `gateway` | Required| One of `elastic_path_payments_stripe`, `authorize_net` and `stripe_payment_intents`. | | `method` | Required | Must be `purchase`. | `payment` | Required | The type of payment, for example, `pm_card_visa_debit`. | `options` | Required | These options must be set as they set up the card to be used in future without the customer being present. If these options are not set, future payments may fail. There are two options. `off_session`. Must be set to `true`. `confirm`. Must be set to `true`. | #### External Payments External payments are payment methods not offered by Elastic Path Subscriptions (such as Elastic Path Payments powered by Stripe or Authorize.net), but they can still be integrated with Subscriptions. To do this, you must configure your subscriptions to use external payments by setting `manual_payments` to `true`. See [Create a Subscription](/docs/api/subscriptions/create-subscription). When a subscription is created with `manual_payments` set to `true`: 1. When the payment run processes the generated invoice, it creates a pending payment. A `subscription-invoice-created` event is emitted that includes the `subscription_id`, `invoice_id` and `payment_id`. No payment is taken. 2. You can use the events generated by Elastic Path Subscriptions to configure your external payment system to respond to these events, ensuring that your external payment system knows when the payment schedule has run and it's time to process the payment. 3. When the external payment system handles the payment (either takes the payment successfully or the payment fails) the [Update Invoice Payment](/docs/api/subscriptions/update-invoice-payment) endpoint, enables the update of the pending payment. - If payment is successful, the invoice is updated to `paid` and the billing/payment cycle continues as normal. - If payment fails, the invoice continues to be marked as `outstanding`. The payment is not `pending` anymore. This is because a payment attempt has been made. Following on from this, the next payment run generates another manual pending payment. The external system is notified of this using the `subscription-invoice-payment-updated`. #### Card Declines Card payments can fail for a variety of reasons, including insufficient funds, incorrect card data or fraudulent activity. You can use the `card_id` and `customer_id` attributes to program your front-end implementation to allow your preferred payment service provider to update a subscription with new card details, enabling you to easily manage your subscription changes. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Jobs(Subscriptions) Jobs are an asynchronous process that can be triggered manually or scheduled. There are three types of job: - a billing run. Subscriptions generates an [**invoice**](/docs/api/subscriptions/invoices) when a billing run occurs. Billing runs generate invoices for the remaining billing cycles for each subscription. The invoice dates come from your pricing options. Billing runs are independent of payment runs. - a tax run. Invoices where `tax_required` is `true` will not have payment taken until a tax run has added the required tax to the invoice. - a payment run. The payment run identifies invoices that are outstanding and attempts to take payment for them. If the payment succeeds the the invoice is no longer outstanding. If the payment fails for any reason, then the invoice remains outstanding and is picked up by the next payment run to retry the payment. By scheduling billing and payment runs, you automate the process, reducing manual intervention and ensuring the jobs are run in a timely manner. See [**Schedules**](/docs/api/subscriptions/schedules). ### Characteristics of Billing, Tax & Payments Jobs Billing and payment jobs have the following characteristics. - Jobs are asynchronous. - Jobs have a different status, depending on where a job is in its lifecycle. - Jobs report any errors to help you understand the reason for any failed jobs. - Only one billing run and payment run is allowed per store at a time. Although billing and payments are constantly generated, the jobs are queued. Subscriptions looks for any jobs that have a status of PENDING and starts the job with the earliest created date. This process is repeated until all jobs are processed. ### Billing, Tax & Payments Jobs Lifecycle A job can have the following status types: - PENDING - Subscriptions has received the request but is currently busy processing other requests. - STARTED - Subscriptions has started processing the job. - SUCCESS - The job has successfully completed. - FAILED - The job has failed. ### Billing, Tax & Payment Reports You can track your Subscriptions billing, payment and tax operations using reports. There are three types of report: - `BillingRunReport` - This report provides invoice summaries such as invoices ready for payment, invoices that require tax, and invoice failures. - `TaxRunReport` - This report provides invoice summaries such as invoices to which tax was successfully or unsuccessfully added. - `PaymentRunReport` - This report provides invoice summaries such as invoices for which payment was attempted, failed payment attempts and totals collected by a payment run. - `NotificationRunReport` - This report provides notification summaries such as notifications sent and failed to send. - `SubscriptionUpdateReport` - This report provides subscription update summaries such as subscriptions that were updated successfully and failed updates. See [Get a job](/docs/api/subscriptions/get-job) and [List jobs](/docs/api/subscriptions/list-jobs). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## List dunning rules import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all dunning rule sets. Request --- ## List features import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all subscription features. ### Filtering This endpoint supports filtering. For the general syntax, see [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | | --- | --- | --- | | `eq` | `external_ref` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | | `eq` | `tag` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | | `in` | `external_ref`, `tag` | In. Checks if the value is in the specified list. If it is, the condition is true. | Request --- ## List import jobs(Subscriptions) import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all import jobs. Request --- ## List invoice payment refunds import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List all refunds for an invoice payments Request --- ## List invoice payments import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List invoice payments Request --- ## List invoices import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all invoices. ### Filtering This endpoint supports filtering. For the general syntax, see [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator |Attribute | Description | | --- | --- | --- | | `eq` | `subscriber_id`, `subscription_id`, `outstanding`, `tax_required` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | | `in` | `subscriber_id`, `subscription_id` | In. Checks if the value is in the specified list. If it is, the condition is true. | Request --- ## List jobs import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all jobs. ### Filtering This endpoint supports filtering. For the general syntax, see [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | | --- | --- | --- | | `eq` | `external_ref` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | | `in` | `external_ref` | In. Checks if the value is in the specified list. If it is, the condition is true. | Request --- ## List an offering's features import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List an offering's features Request --- ## List the pricing options available to a plan in an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List the pricing options available to a plan in an offering Request --- ## List an offering's plans import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List an offering's plans Request --- ## List an offering's pricing options import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List an offering's pricing options Request --- ## List offerings import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all subscription offerings. ### Filtering This endpoint supports filtering. For the general syntax, see [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | | --- | --- | --- | | `eq` | `external_ref`, `plans.external_ref`, `proration_policy_id` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | | `in` | `external_ref`, `plans.external_ref`, `proration_policy_id` | In. Checks if the value is in the specified list. If it is, the condition is true. | Request --- ## List proration policies import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all proration policies. Request --- ## List schedules import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all schedules. ### Filtering This endpoint supports filtering. For the general syntax, see [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | | --- | --- | --- | | `eq` | `external_ref` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | | `in` | `external_ref` | In. Checks if the value is in the specified list. If it is, the condition is true. | Request --- ## List subscribers import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all subscribers. ### Filtering This endpoint supports filtering. For the general syntax, see [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | | --- | --- | --- | | `eq` | `account_id`, `name`, `email`, `external_ref` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | | `in` | `account_id`, `name`, `email`, `external_ref` | In. Checks if the value is in the specified list. If it is, the condition is true. | | `like` | `name`, `email` | Partial match (case-sensitive). Use `*` at the start, end, or both to match any sequence of characters (e.g. `*substring`, `substring*`, `*substring*`). | | `ilike` | `name`, `email` | Partial match (case-insensitive). Same as `like` but matching ignores case. Use `*` at the start, end, or both to match any sequence of characters. | Request --- ## List an subscriptions features import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List an subscriptions features Request --- ## List subscription invoice payments import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Lists all invoice payments for a given invoice. Request --- ## List subscription invoices import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Lists all invoices for a given subscription. Request --- ## List subscription plans import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of plans associated with the specified subscription. Using this endpoint you can see the plan that is currently active in a subscription. If `active_plan` is `true`, a plan is active in a subscription. If `active_plan` is null, the pricing option is not active. Request --- ## List subscription pricing options import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of pricing options associated with the specified subscription. Using this endpoint you can see the pricing options that are currently active in a subscription. If `active_pricing_option` is `true`, a pricing option is active in a subscription. If `active_pricing_option` is null, the pricing option is not active. Request --- ## List subscription states import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; List subscription states Request --- ## List subscriptions import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Retrieves a list of all subscriptions. ### Filtering This endpoint supports filtering. For the general syntax, see [**Filtering**](/guides/Getting-Started/filtering). The following attributes and operators are supported. | Operator | Attribute | Description | | --- | --- | --- | | `eq` | `account_id`, `name`, `email`, `external_ref` | Equals. Checks if the values of two operands are equal. If they are, the condition is true. | | `in` | `account_id`, `name`, `email`, `external_ref` | In. Checks if the value is in the specified list. If it is, the condition is true. | ### Including Resources You can use the `include` parameter to include the following resources with this endpoint. | Resource | Required | Description | | --- | --- | --- | | `pricing_options, plans` | Optional | Retrieves all pricing options and plans associated with a subscription. | | `plans` | Optional | Retrieves all plans associated with a subscription. | | `pricing_options` | Optional | Retrieves all pricing options associated with a subscription. | See [Characteristics of Include Parameter](/guides/Getting-Started/includes#characteristics-of-include-parameter). Request --- ## Manage subscription plans import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Manage subscription plans by replacing, changing or detaching plans on the subscription Request --- ## Offerings An offering is a combination of plans and pricing options; plans are combined with one or more pricing options to form an offering. For example, your company provides online streaming of movies, web-series, and music. Your customers can purchase these services through either a weekly or monthly pricing option. Offering plans can be either: - a subscription plan, created within an offering. - a Product Experience Manager product, see [**Create a product**](/docs/api/pxm/products/create-product) ### Offering Examples Offerings can have any combination of plans and pricing options. The pricing of an offering is determined by the pricing you have configured for your plans and pricing options. | Example | Plan | Pricing options | Offering | | --- | --- | --- | --- | | Single plan and pricing option | One plan with a plan price of $50 | A monthly pricing option with a 5% discount | An offering with a monthly pricing option for $47.50 a month | | Single plan with multiple pricing options | One plan with a plan price of $50 | A monthly pricing option with a 5% discountA yearly pricing option with a 10% discount | An offering with two pricing options: A monthly pricing option for $47.50 a monthA yearly pricing option for $45 a month | | Multiple plans and pricing option | Two plans: One plan with a plan price of $50.One plan with a plan price of $75. | A monthly pricing option with a 5% discount. | An offering with a monthly pricing option for $118.75 a month. | | Multiple plans with multiple pricing options | Two plans: One plan with a plan price of $50.One plan with a plan price of $75. | A monthly pricing option with a 5% discountA yearly pricing option with a 10% discount | An offering with two pricing options: A monthly pricing option for $118.75 a monthA yearly pricing option for $112.50 a month | ### Building an Offering When you are building an offering: - you can create new pricing options and plans. - you can modify existing plans and pricing options. For example, you can modify the plan price or any attributes of a pricing option included in the offering. Here's how you build an offering: When [**building your offerings**](/docs/api/subscriptions/build-offering) you must supply the plans and pricing options that a customer can choose. An offering can consist of many combinations of a plan or pricing options, depending on the plans and services you offer. Plans can either be subscription plans or Product Experience Manager products. To create a Product Experience Manager product, see [**Create a product**](/docs/api/pxm/products/create-product) Pricing options are the rules that govern your subscription, for example, any discount. - You can combine and reuse pricing options for as many plans as you want, making it quick and easy to create your subscription offerings. - An offering must have at least one pricing option. - Each plan must have the appropriate pricing option associated with it When a [**customer**](/docs/api/subscriptions/subscribers) chooses a plan and pricing option, a subscription is created. See [**Subscriptions**](/docs/api/subscriptions/subscriptions). Elastic Path Subscriptions manages the billing and recurring payments associated with the subscription. See [**Invoicing and Billing**](/docs/api/subscriptions/jobs). ### Editing Offerings After saving an offering, you can, at any time: - update an offering's details, for example, name or description. See [**Update an Offering**](/docs/api/subscriptions/update-offering). - update an existing plan in an offering. See [**Update a plan in an offering**](/docs/api/subscriptions/update-offering-plan) - add a new plan in an offering. See [**Create a plan inside an offering**](/docs/api/subscriptions/create-offering-plan) - remove plans. See [**Remove a plan from an offering**](/docs/api/subscriptions/delete-offering-plan). - update an existing pricing option in an offering. See [**Update a pricing option in an offering**](/docs/api/subscriptions/update-offering-pricing-option) - add a new pricing option to an offering. See [**Create a pricing option inside an offering**](/docs/api/subscriptions/create-offering-pricing-option). - remove pricing options. See [**Removing a pricing option from an offering**](/docs/api/subscriptions/delete-offering-plan). Any modifications that you make to offerings, and plans or pricing options in an offering, does not affect any active subscriptions. The changes take effect on all new subscriptions that are created. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Proration Policies Proration is the adjustment of charges or credits on a subscriber's account based on the amount of time a service is used. Proration ensures that subscribers are only charged for the actual time they use the service, whether they upgrade, downgrade, start, or cancel their subscription partway through a billing cycle. This means fair billing for your subscribers and provides you with the flexibility to change your subscribers subscriptions at any time. ::: note Subscriptions use client credentials to enable changes to subscriptions, so if you want your shoppers to have the ability to make changes, you can implement a BFF layer using this approach. ::: Proration occurs for: - Pricing option upgrades/downgrades: If a subscriber changes their pricing option in the middle of a billing cycle, proration adjusts the charges to reflect the time spent on each pricing option. - Service cancellation: If a subscriber cancels a subscription before the end of a billing cycle, they may receive a prorated invoice for the used portion of the subscription. - Mid-cycle subscription: If a subscriber starts a subscription in the middle of a billing cycle, they are charged a prorated amount for the remaining days in the billing cycle. There are several scenarios when implementing proration policies. 1. You may want one policy for multiple offerings because only some subscriptions need prorating. 2. You may want a default proration policy for your store. 3. You may want several policies for different offerings. In Subscriptions, charges only prorate by day. As soon as a subscriber changes their subscription, a manual billing run is triggered and an invoice is generated with the new price on the next billing run and the difference in price is prorated over days. By default, proration is not enabled for Subscriptions. Once you have attached a proration policy to an offering, proration is enabled automatically. ### End dates when switching pricing options Subscriptions manages the subscription end date when shoppers switch from one pricing option to another. Whether or not an end date is configured depends on the end behavior of the pricing options you are switching between. | Current Subscription | New Subscription | Proration Behavior | End date | | --- | --- | --- | --- | | `close` | `roll` | The subscription switches from a pricing option with a fixed end date to a rolling pricing option so no end date is set after proration. | No end date is configured. | | `roll` | `close` | The subscription switches to a fixed pricing option, and the end date is configured based on the duration of the pricing option. | An end date is configured. | | `close` | `close` | The remaining time on the current pricing option is not carried over to the new pricing option. For example, if your current pricing option has 3 months remaining and you switch to a new pricing option that has a fixed length of 6 months, the new end date is calculated as 6 months from the day you switch pricing options, effectively resetting the subscription length to the new pricing option. | New end date calculated from the day you switched pricing option. | ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Removes an offering's pricing options from the plan import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use the unique identifier of the pricing in the offering that you want to update. Any modifications that you make to the plans in an offering, does not affect any active subscriptions. The changes take effect on all new subscriptions that are created. Request --- ## Schedules You can schedule your billing, tax, and payment runs. By scheduling billing, tax, and payment runs, you automate the process, reducing manual intervention and ensuring the jobs are run in a timely manner. You can define a schedule in the format (`* * * * *`) which is a set of five fields in a line, indicating when a job should be executed. For example, you can define a schedule so that your job runs multiple times a day, or runs on specific days and months. Subscriptions runs on Coordinated Universal Time (UTC) time and conforms to [**RFC 3339**](https://www.rfc-editor.org/rfc/rfc3339). ### Unrestricted fields Setting a field to an asterisk (`*`) is sometimes referred to as leaving a field unrestricted because it is not restricted to a specific value. You can use the asterisk (`*`) to indicate the range of all values for the field. When you use the asterisk, the first value in the range is: 0 for the minute, hour, and day of the week (Sunday) fields, and 1 for day of the month and the month fields. ### Configuring fields The time fields have the following format and possible values and must be specified in the following order: | Field | Format | Description | | --- | --- | -----| | Minute | 0-59 | Indicates how far past the top of the hour your job runs, in minutes. For example if a minute is set to 0, then the job runs at the top of the hour because it is 0 minutes after the hour. This means if the hour is 8.00 AM, the job runs at 8.00 AM. | | Hour | 0-23 | Indicates how far past midnight your job runs, in hours. This is rounded down to the nearest hours. This is because minutes are indicated by the minute field. | | Day of the month | 0-31 | Indicates the calendar date of the month. For example, 1 for the first day of the month. | | Month | 1-12 or JAN to DEC | Indicates the month. Specify the month number or the first three letters of the month name in uppercase. For example, 1 or JAN for January. | | Day of the week | 0-6 (or SUN to SAT, or 7 for Sunday) | Indicates the day of the week. Monday is 1, Tuesday is 2, and so on. Either 0 or 7 indicates Sunday. Alternatively, specify the day of the week using the first three letters of the weekday name in uppercase. For example SUN for Sunday. If you use this field with the day of the month field, then this field is evaluated as an inclusive OR. For example, if the day of the month is set to 1 and the day of the week is set to SAT, the job runs on the first day of the month and on every Saturday of the month, even if the first day of the month is not a Saturday. If the day of the week is marked by an asterisk (*) then the field is marked as unrestricted. This means the job only runs on the first day of the month. | ### Matching all values To match all values for a field, set the field to an asterisk (`*`). When a field is set to an asterisk, the field matches all valid values for that field whenever the other field conditions are satisfied. Here are some examples. - `* 0 1 1 1`: the job runs every minute of the midnight hour on January 1st and Mondays. - `* * * * *`: the job runs every minute (of every hour, of every day of the month, of every month, every day of the week, because each of these is unrestricted). ### Matching a range To match a range of values, specify your start and stop values, separated by a hyphen (`-`). Do not include spaces in the range. Ranges are inclusive. The first number must be less than the second number. If you are using abbreviated names for the month or weekday (for example, JAN instead of 1 for the first month of the year), the first value must come earlier in the month or week than the second value. The following equivalent examples run at midnight on Mondays, Tuesdays, Wednesdays, Thursdays, and Fridays (for all months): - `0 0 * * 1-5` - `0 0 * * MON-FRI` ### Matching a list Lists can contain any valid value for the field, including ranges. Specify your values, separated by a comma (,). Do not include spaces in the list. Examples: - `0 0,12 * * *`: the job runs at midnight and noon. - `0-5,30-35 * * * *`: the job runs in each of the first five minutes of every half hour (at the top of the hour and at half past the hour). ### Skipping values in a range You can skip values in a range by specifying a rate at which to step through the range. To do this, specify the range, followed by the forward slash (`/`) and the rate at which you want to skip through the range. The step value cannot be larger than the largest possible value for the field. The default step is 1, so the step function `/1` is the same as not using a step function at all. Example ranges that use step functions: - `*/2`: this is a valid step function for any field. - For the minute field, it matches 0, 2, 4, ... , 58. - For the hour, it matches 0, 2, 4, ... , 22. - For the day of the month, it matches 1, 3, 5, ... , 31 (for a month with 31 days). - For the month, it matches 1, 3, 5, ... , 11. - For the day of the week, it matches 0, 2, 4, 6. - `0-12/2`: this is a valid step function for the minute and hour fields. It matches 0, 2, 4, ... , 12. Example schedules using step functions: - `*/2 * * * *`: the job runs every two minutes. - `0 0-12/2 * * *`: the job runs every two hours, on the hour. The first run is at midnight. The last run is at noon. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Subscribers A subscriber is someone who subscribes to your plan or service. ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Subscriptions Introduction import ApiLogo from "@theme/ApiLogo"; import Heading from "@theme/Heading"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Elastic Path Subscriptions allows you to offer your customers subscriptions and recurring billing for your plans and services. Elastic Path Subscriptions gives you the flexibility to pause, update, or reactivate your subscription offerings, change subscription cycles and apply discounts. You can create subscriptions using the Elastic Path Subscriptions API or Commerce Manager See [Subscriptions](/docs/commerce-manager/subscriptions/overview). Scenarios include: - repeat products that your customers purchase on a recurring basis. - membership subscriptions where your customers pay a recurring fee to become members of a particular service, program or organization. - subscribe and save that allows your customers to subscribe to regular deliveries of products they use frequently, for example, household essentials, or personal care items. ### How Subscriptions Work Elastic Path Subscriptions enables you to manage your subscriptions plans and pricing options, using offerings. Offerings can contain any combination of plans and pricing options. Here's how a typical subscription works: 1. Create your offerings. Offerings are the plan and pricing options that a customer can choose. An offering can consist of many combinations of a plan or pricing options, depending on the plans and services you offer. See [**Offerings**](/docs/api/subscriptions/offerings). 2. When a [**customer**](/docs/api/subscriptions/subscribers) chooses a pricing option, a subscription is created. See [**Subscriptions**](/docs/api/subscriptions/subscriptions). 3. Elastic Path Subscriptions manages the billing and recurring payments associated with the subscription. See [**Invoicing and Payments**](/docs/api/subscriptions/invoices). ### Subscriber Management Elastic Path Subscriptions enables you to create customer accounts that you can use to manage their subscription details, including payment methods and billing information. See [**Subscribers**](/docs/api/subscriptions/subscribers). ### Invoicing & Payments Elastic Path Subscriptions enables you to manage the billing and recurring payments associated with your customers subscriptions. Elastic Path Subscriptions provides seamless integration with Elastic Path Payments powered by Stripe. See [**Invoicing and Payments**](/docs/api/subscriptions/invoices). Security Scheme Type: http HTTP Authorization Scheme: bearer --- ## Subscriptions Elastic Path Subscriptions enables you to manage your subscriptions plans and pricing options, using offerings. Offerings can contain any combination of pricing options and a plan. When a customer chooses a pricing option, a subscription is created. ### Managing the Subscription Lifecycle The subscription lifecycle is the states that a subscription can go through when a customer subscribes to a service or a plan. A subscription can have the following states: - `pending` - `canceled` - `paused` - `resumed` #### Creating a pending subscription A subscription can be created in a `pending` state. This is useful for several reasons. - If there are subscriptions that require user setup or onboarding, for example, installing software or setting up preferences. This helps reduce shopper frustration during the onboarding process, as the shopper is not paying for a service that they cannot use yet. - When offering a free trial or promotion, keeping the subscription in a pending state until the trial or promotion starts or ends allows you to manage transitions more smoothly. - Before a subscription becomes active, you may need to verify the payment method or authorize the first payment. Keeping the subscription in a pending state allows time to complete these steps without activating the subscription. For a subscription with a `pending` state, you can also configure a `go_live_after` date. The subscription starts from the `go_live_after` date. This is useful as it ensures both the subscription provider and subscriber are clear about when a subscription officially begins. Once the `go_live_after` date is passed, the subscription becomes `active`, initiating the billing and payment runs. If a subscription is activated this way, you can see this in the `timestamp` meta. You can configure a `go_live_after` date to be a past date. This is useful, for example, for backdating a subscription or managing a delay in activating a subscription. Setting the `go_live_after` date in the past ensures the subscriptions timeline correctly aligns with the agreed-upon service start date. :::caution Although, billing runs generate one invoice per subscription, if a `go_live_date` is set far in the past, multiple invoices could be generated over the course of several billing runs, which could be frustrating and confusing to your subscribers. ::: See [create a subscription](/docs/api/subscriptions/create-subscription). #### Cancelling or pausing and resuming subscriptions A subscriber can decide to cancel or pause and/or resume a subscription. The following example describes pausing or canceling and resuming a subscription. 1. The subscriber pauses or cancels the subscription. - The subscription status is `active`. - either `paused` or `cancelled` is set to `true`. - either the `paused_at` or `cancelled_at` timestamp is populated with the date and time the subscription is paused or cancelled. - for cancelled subscriptions, `end_date` indicates when the subscription will expire and end. 2. When the next billing run is due, the billing run checks the subscription state. If the subscription state is paused or cancelled then no invoice is created and the subscription status is updated to `inactive`. 3. Subsequent billing runs skip that subscription completely as the subscription status is `inactive`. 4. If the subscriber resumes the subscription: - either `paused` or `cancelled` is set to `false`. - the `resumed_at` timestamp is populated with the date and time the subscription is resumed. 5. When the next billing run is due, the billing run checks the subscription state. If the `paused` or `cancelled` is set to `false` then the billing run creates an invoice. 6. The payment run processes the invoice. Once the payment succeeds then the payment run updates the status of the subscription to `active`. ### Orders When a customer chooses a subscription, they need to add the subscription to a cart, checkout the cart and then pay for the order. 1. When a customer adds a subscription to cart, this is handled using the `Add subscription to cart` endpoint. 2. Once a subscription has been added to a cart, the [**Checkout API**](/docs/api/carts/checkout-api) converts the cart to an order. 3. Once the order is created, payment needs to be taken. This is handled by Elastic Path Payments Powered by Stripe. See [**Payments**](/docs/api/subscriptions/invoices#payments). ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## Update dunning rule policy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the rule is not updated. For fields that are optional, an existing value can be removed by specifying a value of null. Request --- ## Update a feature import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the feature is not updated. For fields that are optional, an existing value can be removed by specifying a value of null. Request --- ## Update Invoice Payment import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; External payment methods are payment methods not offered by Elastic Path Subscriptions (such as Elastic Path Payments powered by Stripe or Authorize.net), but they can still be integrated with Subscriptions. You can use the `Update Invoice Payment` endpoint to manually update a payment against an invoice where an external payment method is handling the payment of your invoices. See [External Payments](/docs/api/subscriptions/invoices#external-payments). Request --- ## Updates a feature in an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use the unique identifier of the feature in the offering that you want to update. Any modifications that you make to the features in an offering, does not affect any active subscriptions. The changes take effect on all new subscriptions that are created. Request --- ## Update a plan in an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Use the unique identifier of the plan in the offering that you want to update. Any modifications that you make to the plans in an offering, does not affect any active subscriptions. The changes take effect on all new subscriptions that are created. Request --- ## Update a pricing option in an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a pricing option in an offering Request --- ## Update an offering import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; After saving an offering, you can update an offering at any time. Updating an offering does not affect any active subscriptions. The changes take effect on all new subscriptions that are created. For fields that are optional, an existing value can be removed by specifying a value of null. Request --- ## Update proration policy import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; You can update a proration policy at any time. For any subscriptions that are using the updated proration policy, the changes are also applied. Specify whichever attributes you want to change. The values of the other attributes remain the same. If the attributes section is empty, the proration policy is not updated. When updating proration policies: - You can change the name of an existing policy. - You can update `rounding`. - You can update `external_ref` as long as `external_ref` is still unique in your store. - You can remove `external_ref` as this attribute is optional. - You cannot remove any required attributes, such as `name` or `rounding`. Request --- ## Update a schedule import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a schedule Request --- ## Update a subscriber import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Update a subscriber Request --- ## Update a subscription import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import ParamsDetails from "@theme/ParamsDetails"; import RequestSchema from "@theme/RequestSchema"; import StatusCodes from "@theme/StatusCodes"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; import Heading from "@theme/Heading"; import Translate from "@docusaurus/Translate"; Updates a subscription. For example, a subscriber can switch from one pricing option to another in a subscription. Request --- ## Security Store administrators and team members share responsibility for keeping a store secure. ## User Credentials Store admins receive their user credentials from Elastic Path to log in to Composable Commerce. Store admins can invite team members to work on a store. After a team member receives an invitation to a Composable Commerce store, they register and create their username and password. Store admins do not have access to the user credentials of the team members. :::caution Never share your user credentials. ::: ## API Authentication Credentials All API requests must contain a generated access token for authentication purposes. To generate an access token, you need your API keys. API keys are the client ID and client secret. Access tokens expire after a predefined period of time. Application keys are used to manage your stores directly. They are not associated to a specific user, and are identified based on their names. :::caution Never share your API keys or generated access tokens. ::: You can generate different types of access tokens based on the level of access needed for a particular task. - `client_credentials` token - Enables full access to all resources in the store. Use this type of token to create, read, update, or delete resources by using the API. - `implicit` token - Enables read access to resources in the store. Use this type of token to perform actions that a store customer would do, that is, access live resources available from the storefront. In addition, an `account` or `customer` token is required to access a shopper profile, including addresses and order history when using an `implicit` token. :::caution Removing a team member removes the unique ClientID and Client Secret associated with that team member. ::: ## Single Sign-on Single sign-on allows authentication with Commerce using an external authentication provider. Using an existing authentication provider allows for integration with company-specific or customizable authentication systems. In some cases, it can also simplify the log-in experience because they don’t need to remember another password. For more information, see [Single Sign-on](/docs/api/single-sign-on). ## Related Resources - [Your first API request](/guides/Getting-Started/your-first-api-request) - [Authentication](/docs/api/authentication) - [Application Keys](/docs/api/application-keys/application-keys-introduction) --- ## Get Customer Authentication Settings ## `GET` Get Customer Authentication Settings ```http https://useast.api.elasticpath.com/v2/settings/customer-authentication ``` ## Parameters ### Headers | Name | Required | Type | Description | | --- | --- | --- | --- | | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | ## Request Examples ### Curl ```bash curl -X GET https://useast.api.elasticpath.com/v2/settings/customer-authentication \ -H "Authorization: Bearer XXXX" \ ``` ### JavaScript SDK ```javascript const MoltinGateway = require("@moltin/sdk").gateway; const Moltin = MoltinGateway({ client_id: "X", }); Moltin.AuthenticationSettings.Get().then((authenticationSettings) => { // Do something }); // Where `EPCC` is an authenticated client await EPCC.AuthenticationSettingsEndpoint.Get(); ``` ## Response Example `200 OK` ```json { "data": { "id": "88888888-4444-4333-8333-111111111111", "meta": { "client_id": "customers" }, "relationships": { "authentication-realm": { "data": { "id": "40086652-2779-45f0-8ea6-ae630dfd13cb", "links": { "self": "https://useast.api.elasticpath.com/v2/authentication-realms/40086652-2779-45f0-8ea6-ae630dfd13cb" }, "duplicate_email_policy": "allowed", "type": "authentication-realm" } } }, "type": "customer-authentication-settings" } } ``` --- ## Customer Authentication Settings You can use the Customer Authentication Settings endpoint to retrieve settings controlling customer authentication. ## The Customer Authentication Settings object | Attribute | Type | Description | | :--- | :--- | :--- | | `id` | `string` | The unique identifier for these customer authentication settings. | | `meta` | `object` | Additional information for these customer authentication settings. Also see: [The meta object](#the-meta-object) below. | | `relationships` | `object` | Related resources. Also see: [The relationships object](#the-relationships-object) below. | | `type` | `string` | The type represents the object being returned. | ## Sample Object ```json { "data": { "id": "88888888-4444-4333-8333-111111111111", "meta": { "client_id": "customers" }, "relationships": { "authentication-realm": { "data": { "id": "40086652-2779-45f0-8ea6-ae630dfd13cb", "links": { "self": "https://useast.api.elasticpath.com/v2/authentication-realms/40086652-2779-45f0-8ea6-ae630dfd13cb" }, "duplicate_email_policy": "allowed", "type": "authentication-realm" } } }, "type": "customer-authentication-settings" } } ``` ## The `meta` object | Attribute | Type | Description | | :--- | :--- | :--- | | `meta.client_id` | `string` | The client id to be used in Single Sign On authentication flows for customers. For more information on where to use this client id, refer to the Developer How-To: [Single sign-on with OpenID Connect](/guides/How-To/Authentication/get-single-sign-on-account-management-token). | ## The `relationships` object | Attribute | Type | Description | | :--- | :--- | :--- | | `relationships.authentication-realm` | `object` | Relationship information regarding the authentication realm entity used for authentication for this store. | | `relationships.authentication-realm.data` | `object` | Information regarding the authentication realm entity. | | `relationships.authentication-realm.data.id` | `string` | The id of the authentication realm entity. | | `relationships.authentication-realm.data.type` | `string` | The type of the authentication realm entity. | --- ## Permissions Permissions are managed through tokens. There are two authentication methods, `client_credentials` and `implicit`. See [Client credentials vs Implicit](/docs/api/authentication/authentication#client-credentials-vs-implicit-use-case-scenarios) for the difference. [Account management authentication token](/docs/api/authentication/authentication#account-authentication) combined with an `implicit` access token is used to manage user interfaces that involve restricted account related data. This data may include orders, addresses, and account details. [Customer token](/docs/api/authentication/authentication#customer-authentication) combined with an `implicit` access token is used to manage user interfaces that involve restricted customer related data. This data may include orders, addresses, and customer details. ## Breakdown of Access (for shoppers) The following tables show a breakdown of the API endpoint actions that are available to the implicit token. ### Implicit | Endpoint | Read access | Write access | |----------------------------------------------| --- | --- | | `/accounts` | ⛔️ | ⛔️ | | `/account-members` | ⛔️ | ⛔️ | | `/account-membership` | ⛔️ | ⛔️ | | `/application-keys` | ⛔️ | ⛔️ | | `/authentication-realms` | ✅ | ⛔️ | | `/brands` | ✅ | ⛔️ | | `/carts` | ✅ | ✅ | | `/categories` | ✅ | ⛔️ | | `/checkout` | ✅ | ✅ | | `/collections` | ✅ | ⛔️ | | `/currencies` | ✅ | ⛔️ | | `/customers` | ⛔️ | ⛔️ | | `/files` | ✅ | ⛔️ | | `/flows` | ✅ | ⛔️ | | `/gateways` | ⛔️ | ⛔️ | | `/integrations` | ⛔️ | ⛔️ | | `/inventories` | ✅ | ⛔️ | | `/jobs` | ⛔️ | ⛔️ | | `/pcm/jobs` | ⛔️ | ⛔️ | | `/merchant-realm-mappings` | ⛔️ | ⛔️ | | `/orders` | ⛔️ | ⛔️ | | `/orders/:id` | ⛔️ | ⛔️ | | `/v2/products` | ✅ | ⛔️ | | `/catalog/products` | ✅ | ⛔️ | | `/catalog/hierarchies` | ✅ | ⛔️ | | `/catalog/nodes` | ✅ | ⛔️ | | `/pcm/products` | ⛔️ | ⛔️ | | `/pcm/hierarchies` | ⛔️ | ⛔️ | | `/pcm/pricebooks` | ⛔️ | ⛔️ | | `/pcm/catalogs` | ⛔️ | ⛔️ | | `/permissions` | ⛔️ | ⛔️ | | `/promotions` | ⛔️ | ⛔️ | | `/settings` | ⛔️ | ⛔️ | | `/settings/account-authentication` | ⛔️ | ⛔️ | | `/settings/customer-authentication` | ⛔️ | ⛔️ | | `/settings/extensions` | ⛔️ | ⛔️ | | `/variations` | ⛔️ | ⛔️ | ### Implicit + Account Management Authentication Token | Endpoint | Read access | Write access | |----------------------------------------------|-------------|--------------| | `/accounts` | ✅️ | ⛔️ | | `/account-members` | ✅️ | ⛔️ | | `/account-membership` | ✅ | ⛔️ | | `/application-keys` | ⛔️ | ⛔️ | | `/authentication-realms` | ✅ | ⛔️ | | `/brands` | ✅ | ⛔️ | | `/carts` | ✅ | ✅ | | `/categories` | ✅ | ⛔️ | | `/checkout` | ✅ | ✅ | | `/collections` | ✅ | ⛔️ | | `/currencies` | ✅ | ⛔️ | | `/customers` | ⛔ | ⛔ | | `/files` | ✅ | ⛔️ | | `/flows` | ✅ | ⛔️ | | `/gateways` | ⛔️ | ⛔️ | | `/integrations` | ⛔️ | ⛔️ | | `/inventories` | ✅ | ⛔️ | | `/jobs` | ⛔️ | ⛔️ | | `/pcm/jobs` | ⛔️ | ⛔️ | | `/merchant-realm-mappings` | ⛔️ | ⛔️ | | `/orders` | ✅ | ⛔️ | | `/orders/:id` | ✅ | ⛔️ | | `/v2/products` | ✅ | ⛔️ | | `/catalog/products` | ✅ | ⛔️ | | `/catalog/hierarchies` | ✅ | ⛔️ | | `/catalog/nodes` | ✅ | ⛔️ | | `/pcm/products` | ⛔️ | ⛔️ | | `/pcm/hierarchies` | ⛔️ | ⛔️ | | `/pcm/pricebooks` | ⛔️ | ⛔️ | | `/pcm/catalogs` | ⛔️ | ⛔️ | | `/permissions` | ⛔️ | ⛔️ | | `/promotions` | ⛔️ | ⛔️ | | `/settings` | ⛔️ | ⛔️ | | `/settings/account-authentication` | ⛔️ | ⛔️ | | `/settings/customer-authentication` | ⛔️ | ⛔️ | | `/settings/extensions` | ⛔️ | ⛔️ | | `/variations` | ⛔️ | ⛔️ | Note that you can only fetch data with live status. ### Implicit + Customer Token | Endpoint | Read access | Write access | |----------------------------------------------|-------------|--------------| | `/accounts` | ⛔️ | ⛔️ | | `/account-members` | ⛔️ | ⛔️ | | `/account-membership` | ⛔️ | ⛔️ | | `/application-keys` | ⛔️ | ⛔️ | | `/authentication-realms` | ✅ | ⛔️ | | `/brands` | ✅ | ⛔️ | | `/carts` | ✅ | ✅ | | `/categories` | ✅ | ⛔️ | | `/checkout` | ✅ | ✅ | | `/collections` | ✅ | ⛔️ | | `/currencies` | ✅ | ⛔️ | | `/customers` | ✅ | ✅ | | `/files` | ✅ | ⛔️ | | `/flows` | ✅ | ⛔️ | | `/gateways` | ⛔️ | ⛔️ | | `/integrations` | ⛔️ | ⛔️ | | `/inventories` | ✅ | ⛔️ | | `/jobs` | ⛔️ | ⛔️ | | `/pcm/jobs` | ⛔️ | ⛔️ | | `/merchant-realm-mappings` | ⛔️ | ⛔️ | | `/orders` | ✅ | ⛔️ | | `/orders/:id` | ✅ | ⛔️ | | `/v2/products` | ✅ | ⛔️ | | `/catalog/products` | ✅ | ⛔️ | | `/catalog/hierarchies` | ✅ | ⛔️ | | `/catalog/nodes` | ✅ | ⛔️ | | `/pcm/products` | ⛔️ | ⛔️ | | `/pcm/hierarchies` | ⛔️ | ⛔️ | | `/pcm/pricebooks` | ⛔️ | ⛔️ | | `/pcm/catalogs` | ⛔️ | ⛔️ | | `/permissions` | ⛔️ | ⛔️ | | `/promotions` | ⛔️ | ⛔️ | | `/settings` | ⛔️ | ⛔️ | | `/settings/account-authentication` | ⛔️ | ⛔️ | | `/settings/customer-authentication` | ⛔️ | ⛔️ | | `/settings/extensions` | ⛔️ | ⛔️ | | `/variations` | ⛔️ | ⛔️ | ## Breakdown of Access (for sellers) The following tables show a breakdown of the API endpoint actions that are available to the client credentials token for each role. Refer to the [Team Management](/guides/Getting-Started/team-management) page for a comparison of different roles. ### Seller admin | Endpoint | Read access | Write access | |----------------------------------------------|-------------|--------------| | `/accounts` | ✅ | ✅ | | `/account-members` | ✅ | ✅ | | `/account-membership` | ✅ | ✅ | | `/application-keys` | ✅ | ✅ | | `/authentication-realms` | ✅ | ✅ | | `/brands` | ✅ | ✅ | | `/carts` | ✅ | ✅ | | `/categories` | ✅ | ✅ | | `/checkout` | ✅ | ✅ | | `/collections` | ✅ | ✅ | | `/currencies` | ✅ | ✅ | | `/customers` | ✅ | ✅ | | `/files` | ✅ | ✅ | | `/flows` | ✅ | ✅ | | `/gateways` | ✅ | ✅ | | `/integrations` | ✅ | ✅ | | `/inventories` | ✅ | ✅ | | `/jobs` | ✅ | ✅ | | `/pcm/jobs` | ✅ | ✅ | | `/personal-data/logs` | ✅ | ✅ | | `/personal-data/personal-data-entries` | ✅ | ✅ | | `/merchant-realm-mappings` | ✅ | ✅ | | `/orders` | ✅ | ✅ | | `/orders/:id` | ✅ | ✅ | | `/v2/products` | ✅ | ✅ | | `/catalog/products` | ✅ | ✅ | | `/catalog/hierarchies` | ✅ | ✅ | | `/catalog/nodes` | ✅ | ✅ | | `/pcm/products` | ✅ | ✅ | | `/pcm/hierarchies` | ✅ | ✅ | | `/pcm/pricebooks` | ✅ | ✅ | | `/pcm/catalogs` | ✅ | ✅ | | `/permissions` | ✅ | ✅ | | `/promotions` | ✅ | ✅ | | `/settings` | ✅ | ✅ | | `/settings/account-authentication` | ✅ ️ | ⛔ | | `/settings/customer-authentication` | ✅ | ⛔ | | `/settings/extensions` | ✅ | ✅ | | `/subscriptions` | ✅ | ✅ | | `/user-roles` | ✅ | ✅ | | `/variations` | ✅ | ✅ | ### Basic user | Endpoint | Read access | Write access | |----------------------------------------| --- | --- | | `/accounts` | ✅️ | ✅️ | | `/account-members` | ⛔️ | ⛔️ | | `/account-membership` | ⛔️ | ⛔️ | | `/application-keys` | ⛔️ | ⛔️ | | `/authentication-realms` | ⛔️ | ⛔️ | | `/brands` | ⛔️ | ⛔️ | | `/carts` | ⛔️ | ⛔️ | | `/categories` | ⛔️ | ⛔️ | | `/checkout` | ⛔️ | ⛔️ | | `/collections` | ⛔️ | ⛔️ | | `/currencies` | ✅️ | ⛔️ | | `/customers` | ✅️ | ✅️ | | `/files` | ⛔️ | ⛔️ | | `/flows` | ✅️ | ⛔️ | | `/gateways` | ⛔️ | ⛔️ | | `/integrations` | ⛔️ | ⛔️ | | `/inventories` | ✅ | ⛔️ | | `/jobs` | ⛔️ | ⛔️ | | `/pcm/jobs` | ⛔️ | ⛔️ | | `/personal-data/logs` | ⛔️ | ⛔️ | | `/personal-data/personal-data-entries` | ⛔️ | ⛔️ | | `/merchant-realm-mappings` | ⛔️ | ⛔️ | | `/orders` | ⛔️ | ⛔️ | | `/orders/:id` | ⛔️ | ⛔️ | | `/v2/products` | ⛔️ | ⛔️ | | `/catalog/products` | ⛔️ | ⛔️ | | `/catalog/hierarchies` | ⛔️ | ⛔️ | | `/catalog/nodes` | ⛔️ | ⛔️ | | `/pcm/products` | ⛔️ | ⛔️ | | `/pcm/hierarchies` | ⛔️ | ⛔️ | | `/pcm/pricebooks` | ⛔️ | ⛔️ | | `/pcm/catalogs` | ⛔️ | ⛔️ | | `/permissions` | ⛔️ | ⛔️ | | `/promotions` | ⛔️ | ⛔️ | | `/settings` | ⛔️ | ⛔️ | | `/settings/account-authentication` | ⛔️ | ⛔️ | | `/settings/customer-authentication` | ⛔️ | ⛔️ | | `/settings/extensions` | ⛔️ | ⛔️ | | `/subscriptions ` | ⛔️ | ⛔️ | | `/user-roles` | ✅ | ⛔️ | | `/variations` | ⛔️ | ⛔️ | ### Marketing/Sales | Endpoint | Read access | Write access | |----------------------------------------| --- | --- | | `/accounts` | ⛔️ | ⛔️ | | `/account-members` | ⛔️ | ⛔️ | | `/account-membership` | ⛔️ | ⛔️ | | `/application-keys` | ⛔️ | ⛔️ | | `/authentication-realms` | ⛔ | ⛔ | | `/brands` | ✅ | ✅ | | `/carts` | ⛔ | ⛔ | | `/categories` | ✅ | ✅ | | `/checkout` | ⛔ | ⛔ | | `/collections` | ✅ | ✅ | | `/currencies` | ✅ | ⛔ | | `/customers` | ⛔ | ⛔ | | `/files` | ✅ | ✅ | | `/flows` | ✅ | ✅ | | `/gateways` | ⛔️ | ⛔️ | | `/integrations` | ⛔ | ⛔ | | `/inventories` | ✅ | ✅ | | `/jobs` | ⛔ | ⛔ | | `/pcm/jobs` | ✅ | ✅ | | `/personal-data/logs` | ⛔️ | ⛔️ | | `/personal-data/personal-data-entries` | ⛔️ | ⛔️ | | `/merchant-realm-mappings` | ⛔ | ⛔ | | `/orders` | ⛔ | ⛔ | | `/orders/:id` | ⛔ | ⛔ | | `/v2/products` | ✅ | ✅ | | `/catalog/products` | ✅ | ⛔️ | | `/catalog/hierarchies` | ✅ | ⛔️ | | `/catalog/nodes` | ✅ | ⛔️ | | `/pcm/products` | ✅ | ✅ | | `/pcm/hierarchies` | ✅ | ✅ | | `/pcm/pricebooks` | ✅ | ✅ | | `/pcm/catalogs` | ✅ | ✅ | | `/permissions` | ⛔️ | ⛔️ | | `/promotions` | ✅ | ✅ | | `/settings` | ⛔ | ⛔ | | `/settings/account-authentication` | ⛔️ | ⛔️ | | `/settings/customer-authentication` | ⛔️ | ⛔️ | | `/settings/extensions` | ⛔️ | ⛔️ | | `/subscriptions` | ⛔️ | ⛔️ | | `/user-roles` | ✅ | ⛔ | | `/variations` | ✅ | ✅ | ### Support | Endpoint | Read access | Write access | |----------------------------------------| --- | --- | | `/accounts` | ✅️ | ✅️ | | `/account-members` | ✅️ | ✅️ | | `/account-membership` | ✅️ | ✅️ | | `/application-keys` | ⛔️ | ⛔️ | | `/authentication-realms` | ⛔️ | ⛔️ | | `/brands` | ⛔️ | ⛔️ | | `/carts` | ⛔️ | ⛔️ | | `/categories` | ⛔️ | ⛔️ | | `/checkout` | ⛔️ | ⛔️ | | `/collections` | ⛔️ | ⛔️ | | `/currencies` | ✅️ | ⛔️ | | `/customers` | ✅️ | ✅️ | | `/files` | ⛔️ | ⛔️ | | `/flows` | ✅️ | ⛔️ | | `/gateways` | ⛔️ | ⛔️ | | `/integrations` | ⛔️ | ⛔️ | | `/inventories` | ⛔️ | ⛔️ | | `/jobs` | ⛔️ | ⛔️ | | `/pcm/jobs` | ⛔️ | ⛔️ | | `/personal-data/logs` | ✅ | ✅️ | | `/personal-data/personal-data-entries` | ✅ | ✅️ | | `/merchant-realm-mappings` | ⛔️ | ⛔️ | | `/orders` | ✅ | ✅️ | | `/orders/:id` | ✅ | ✅️ | | `/v2/products` | ⛔️ | ⛔️ | | `/catalog/products` | ⛔️ | ⛔️ | | `/catalog/hierarchies` | ⛔️ | ⛔️ | | `/catalog/nodes` | ⛔️ | ⛔️ | | `/pcm/products` | ⛔️ | ⛔️ | | `/pcm/hierarchies` | ⛔️ | ⛔️ | | `/pcm/pricebooks` | ⛔️ | ⛔️ | | `/pcm/catalogs` | ⛔️ | ⛔️ | | `/permissions` | ⛔️ | ⛔️ | | `/promotions` | ⛔️ | ⛔️ | | `/settings` | ⛔️ | ⛔️ | | `/settings/account-authentication` | ✅️ | ⛔️ | | `/settings/customer-authentication` | ✅️ | ⛔️ | | `/settings/extensions` | ⛔️ | ⛔️ | | `/subscriptions` | ⛔️ | ⛔️ | | `/user-roles` | ✅ | ⛔️ | | `/variations` | ⛔️ | ⛔️ | ### IT/Developer | Endpoint | Read access | Write access | |----------------------------------------| --- | --- | | `/accounts` | ⛔️ | ⛔️ | | `/account-members` | ⛔️ | ⛔️ | | `/account-membership` | ⛔️ | ⛔️ | | `/application-keys` | ✅ | ✅ | | `/authentication-realms` | ✅️ | ✅ | | `/brands` | ⛔️ | ⛔️ | | `/carts` | ⛔️ | ⛔️ | | `/categories` | ⛔️ | ⛔️ | | `/checkout` | ⛔️ | ⛔️ | | `/collections` | ⛔️ | ⛔️ | | `/currencies` | ✅️ | ✅️ | | `/customers` | ⛔️ | ⛔️ | | `/files` | ⛔️ | ⛔️ | | `/flows` | ✅️ | ✅️ | | `/gateways` | ✅️️ | ✅️️ | | `/integrations` | ✅️ | ✅️ | | `/inventories` | ⛔️ | ⛔️ | | `/jobs` | ⛔️ | ⛔️ | | `/pcm/jobs` | ⛔️ | ⛔️ | | `/personal-data/logs` | ✅ | ✅️ | | `/personal-data/personal-data-entries` | ✅ | ✅️ | | `/merchant-realm-mappings` | ✅ | ✅️ | | `/orders` | ⛔️ | ⛔️ | | `/orders/:id` | ⛔️ | ⛔️ | | `/v2/products` | ⛔️ | ⛔️ | | `/catalog/products` | ⛔️ | ⛔️ | | `/catalog/hierarchies` | ⛔️ | ⛔️ | | `/catalog/nodes` | ⛔️ | ⛔️ | | `/pcm/products` | ⛔️ | ⛔️ | | `/pcm/hierarchies` | ⛔️ | ⛔️ | | `/pcm/pricebooks` | ⛔️ | ⛔️ | | `/pcm/catalogs` | ⛔️ | ⛔️ | | `/permissions` | ✅ | ✅️ | | `/promotions` | ⛔️ | ⛔️ | | `/settings` | ⛔️ | ⛔️ | | `/settings/account-authentication` | ✅️ | ⛔ | | `/settings/customer-authentication` | ✅️ | ⛔ | | `/settings/extensions` | ✅ | ✅️ | | `/subscriptions` | ✅ | ✅️ | | `/user-roles` | ✅ | ✅️ | | `/variations` | ⛔️ | ⛔️ | ### Promotions Manager | Endpoint | Read access | Write access | |----------------------------------------------| --- | --- | | `/accounts` | ⛔️ | ⛔️ | | `/account-members` | ⛔️ | ⛔️ | | `/account-membership` | ⛔️ | ⛔️ | | `/application-keys` | ⛔️ | ⛔️ | | `/authentication-realms` | ⛔ | ⛔ | | `/brands` | ⛔ | ⛔ | | `/carts` | ⛔ | ⛔ | | `/categories` | ⛔ | ⛔ | | `/checkout` | ⛔ | ⛔ | | `/collections` | ⛔ | ⛔ | | `/currencies` | ✅ | ⛔ | | `/customers` | ⛔ | ⛔ | | `/files` | ⛔️ | ⛔ | | `/flows` | ✅ | ⛔ | | `/gateways` | ⛔️ | ⛔️ | | `/integrations` | ⛔ | ⛔ | | `/inventories` | ⛔ | ⛔ | | `/jobs` | ⛔ | ⛔ | | `/pcm/jobs` | ⛔ | ⛔ | | `/personal-data/logs` | ⛔️ | ⛔️ | | `/personal-data/personal-data-entries` | ⛔️ | ⛔️ | | `/merchant-realm-mappings` | ⛔ | ⛔ | | `/orders` | ⛔ | ⛔ | | `/orders/:id` | ⛔ | ⛔ | | `/v2/products` | ⛔ | ⛔ | | `/catalog/products` | ⛔ | ⛔️ | | `/catalog/hierarchies` | ⛔ | ⛔️ | | `/catalog/nodes` | ⛔ | ⛔️ | | `/pcm/products` | ✅ | ⛔ | | `/pcm/hierarchies` | ✅ | ⛔ | | `/pcm/pricebooks` | ⛔ | ⛔ | | `/pcm/catalogs` | ✅ | ⛔ | | `/permissions` | ⛔️ | ⛔️ | | `/promotions` | ✅ | ✅ | | `/settings` | ⛔ | ⛔ | | `/settings/account-authentication` | ⛔️ | ⛔️ | | `/settings/customer-authentication` | ⛔️ | ⛔️ | | `/settings/extensions` | ⛔️ | ⛔️ | | `/subscriptions` | ⛔️ | ⛔️ | | `/user-roles` | ✅ | ⛔ | | `/variations` | ⛔ | ⛔ | ### eCommerce Admin | Endpoint | Read access | Write access | |----------------------------------------| --- | --- | | `/accounts` | ✅ | ✅ | | `/account-members` | ✅ | ✅ | | `/account-membership` | ✅ | ✅ | | `/application-keys` | ⛔️ | ⛔️ | | `/authentication-realms` | ⛔ | ⛔ | | `/brands` | ✅ | ✅ | | `/carts` | ⛔ | ⛔ | | `/categories` | ✅ | ✅ | | `/checkout` | ⛔ | ⛔ | | `/collections` | ✅ | ✅ | | `/currencies` | ✅ | ⛔ | | `/customers` | ✅ | ✅ | | `/files` | ✅ | ✅ | | `/flows` | ✅ | ✅ | | `/gateways` | ⛔️ | ⛔️ | | `/integrations` | ⛔ | ⛔ | | `/inventories` | ✅ | ✅ | | `/jobs` | ⛔ | ⛔ | | `/pcm/jobs` | ✅ | ✅ | | `/personal-data/logs` | ✅ | ✅ | | `/personal-data/personal-data-entries` |✅ | ✅ | | `/merchant-realm-mappings` | ⛔ | ⛔ | | `/orders` | ✅ | ✅ | | `/orders/:id` | ✅ | ✅ | | `/v2/products` | ✅ | ✅ | | `/catalog/products` | ✅ | ⛔️ | | `/catalog/hierarchies` | ✅ | ⛔️ | | `/catalog/nodes` | ✅ | ⛔️ | | `/pcm/products` | ✅ | ✅ | | `/pcm/hierarchies` | ✅ | ✅ | | `/pcm/pricebooks` | ✅ | ✅ | | `/pcm/catalogs` | ✅ | ✅ | | `/permissions` | ⛔️ | ⛔️ | | `/promotions` | ✅ | ✅ | | `/settings` | ⛔ | ⛔ | | `/settings/account-authentication` | ✅ | ⛔️ | | `/settings/customer-authentication` | ✅ | ⛔️ | | `/settings/extensions` | ⛔️ | ⛔️ | | `/subscriptions ` | ⛔️ | ⛔️ | | `/user-roles` | ✅ | ⛔ | | `/variations` | ✅ | ✅ | ## Related Resources - [Team Management](/guides/Getting-Started/team-management) --- ## Includes You can use `include=promotions` to retrieve condensed promotion from the following endpoints: - [Get a Cart](/docs/api/carts/get-a-cart) - [Get Cart Items](/docs/api/carts/get-cart-items) - [Get an Order](/docs/api/carts/get-an-order) - [Get Order Items](/docs/api/carts/get-order-items) See [Condensed promotions](/docs/api/promotions/promotions-standard-introduction#condensed-promotion). When a promotion is deleted, the discount associated with it becomes inactive. If the promotion is deleted but still remains in the cart, it does not appear in the `included` section of the response body. ## `GET` Retrieve Promotions from a Cart ```http https://useast.api.elasticpath.com/v2/carts/:id?include=promotions ``` ## Parameters ### Path parameters | Name | Required | Type | Description | |:------------|:---------|:---------|:-----------------------------------------| | `id` | Required | `string` | The unique identifier of the cart that you created. | ### Headers | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | ### Query parameters | Name | Required | Type | Description | |:----------|:---------|:---------|:-------------------------------------------| | `include` | Optional | `string` | The promotions for a cart. | ## Request Example - Curl ```bash curl -X GET https://useast.api.elasticpath.com/v2/carts/:id?include=promotions \ -H "Authorization: Bearer XXXX" ``` ## Response Example The following response example shows condensed promotions for cart discounts within the included object. When you create a cart discount rule promotion, an item discount rule promotion and a standard cart discount promotion, and apply these discounts to a cart with eligible items, then upon calling `GET {{baseUrl}}/carts/{{cartID}}?include=promotions` endpoint, the cart relationship object has the promotion item. Additionally, the `included` object contains condensed promotions for the cart discounts. `200 OK` ```json { "data": { "id": "1", "type": "cart", "name": "my cart name", "description": "cart description", "discount_settings": { "custom_discounts_enabled": false, "use_rule_promotions": true }, "links": { "self": "https://useast.api.elasticpath.com/v2/carts/1" }, "meta": { "display_price": { "with_tax": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "without_tax": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "tax": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "discount": { "amount": -4000, "currency": "USD", "formatted": "-$40.00" }, "without_discount": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "shipping": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2024-05-24T17:38:10Z", "updated_at": "2024-05-31T16:26:07Z", "expires_at": "2024-06-07T16:26:07Z" } }, "relationships": { "items": { "data": [ { "type": "promotion_item", "id": "0bf2c5d6-0930-48c3-86da-f0ae6fcb0ad7" }, { "type": "cart_item", "id": "1a317de0-5375-4175-8a0d-7ecea776fb89" }, { "type": "promotion_item", "id": "1fec2974-3578-4b7d-bd7e-2ed626cbec2c" } ] }, "customers": {}, "accounts": {}, "promotions": { "data": [ { "type": "promotion", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44" }, { "type": "promotion", "id": "05b35539-7946-4145-a8ff-bfd3cefc7691" } ] } } }, "included": { "promotions": [ { "type": "promotion", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44", "name": "cart20", "description": "cart20", "automatic": false, "promotion_source": "rule-promotion", "start": "2024-04-01T18:24:06Z", "end": "2024-06-01T18:24:09Z" }, { "type": "promotion", "id": "05b35539-7946-4145-a8ff-bfd3cefc7691", "name": "v1cart10", "description": "v1cart10", "automatic": false, "promotion_type": "fixed_discount", "start": "2024-04-01T17:25:00Z", "end": "2024-06-01T17:25:03Z" } ] } } ``` ## GET Retrieve Promotions from Cart Items ```http https://useast.api.elasticpath.com/v2/carts/:id/items?include=promotions` ``` ## Parameters ### Path parameters | Name | Required | Type | Description | |:------------|:---------|:---------|:-----------------------------------------| | `id` | Required | `string` | The unique identifier of the cart that you created. | ### Headers | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | ### Query parameters | Name | Required | Type | Description | |:----------|:---------|:---------|:-------------------------------------------| | `include` | Optional | `string` | The promotions for cart items. | ## Request Example - Curl ```bash curl -X GET https://useast.api.elasticpath.com/v2/carts/:id/items?include=promotions \ -H "Authorization: Bearer XXXX" ``` ## Response Example The following response example shows condensed promotion for both cart discount and item discounts. `200 OK` ```json { "data": [ { "id": "1a317de0-5375-4175-8a0d-7ecea776fb89", "type": "cart_item", "product_id": "5a4662d2-9a2b-4f6e-a215-2970db914b0c", "name": "sku1", "description": "sku1", "sku": "sku1", "slug": "sku1", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": false, "unit_price": { "amount": 10000, "currency": "USD", "includes_tax": false }, "value": { "amount": 10000, "currency": "USD", "includes_tax": false }, "discounts": [ { "amount": { "amount": -1000, "currency": "USD", "includes_tax": false }, "code": "sale2024", "id": "de19a043-a6da-4bde-b896-d17e16b77e25", "promotion_source": "rule-promotion" }, { "amount": { "amount": -2000, "currency": "USD", "includes_tax": false }, "code": "sale2024", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44", "promotion_source": "rule-promotion", "is_cart_discount": true } ], "links": { "product": "https://useast.api.elasticpath.com/v2/products/5a4662d2-9a2b-4f6e-a215-2970db914b0c" }, "relationships": { "taxes": { "data": null }, "custom_discounts": { "data": null }, "promotions": { "data": [ { "type": "promotion", "id": "de19a043-a6da-4bde-b896-d17e16b77e25" }, { "type": "promotion", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44" } ] } }, "meta": { "display_price": { "with_tax": { "unit": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "value": { "amount": 6000, "currency": "USD", "formatted": "$60.00" } }, "without_tax": { "unit": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "value": { "amount": 6000, "currency": "USD", "formatted": "$60.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "discount": { "unit": { "amount": -4000, "currency": "USD", "formatted": "-$40.00" }, "value": { "amount": -4000, "currency": "USD", "formatted": "-$40.00" } }, "without_discount": { "unit": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "value": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } }, "discounts": { "sale2024": { "amount": -3000, "currency": "USD", "formatted": "-$30.00", "constituents": { "de19a043-a6da-4bde-b896-d17e16b77e25": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" }, "e4d929d5-f471-4317-9a86-a84a6c572b44": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" } } } } }, "timestamps": { "created_at": "2024-05-31T16:26:04Z", "updated_at": "2024-05-31T16:26:04Z" } }, "catalog_id": "09b9359f-897f-407f-89a2-702e167fe781", "catalog_source": "pim" }, { "id": "0bf2c5d6-0930-48c3-86da-f0ae6fcb0ad7", "type": "promotion_item", "promotion_id": "e4d929d5-f471-4317-9a86-a84a6c572b44", "name": "cart20", "description": "Promotion", "sku": "sale2024", "slug": "", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": false, "unit_price": { "amount": -2000, "currency": "USD", "includes_tax": false }, "value": { "amount": -2000, "currency": "USD", "includes_tax": false }, "links": {}, "relationships": { "taxes": { "data": null }, "custom_discounts": { "data": null }, "promotions": { "data": [ { "type": "promotion", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44" } ] } }, "meta": { "display_price": { "with_tax": { "unit": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" }, "value": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" } }, "without_tax": { "unit": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" }, "value": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "discount": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "without_discount": { "unit": { "amount": 0, "currency": "", "formatted": "0" }, "value": { "amount": 0, "currency": "", "formatted": "0" } } }, "timestamps": { "created_at": "2024-05-31T16:26:07Z", "updated_at": "2024-05-31T16:26:07Z" } }, "promotion_source": "rule-promotion" }, { "id": "1fec2974-3578-4b7d-bd7e-2ed626cbec2c", "type": "promotion_item", "promotion_id": "05b35539-7946-4145-a8ff-bfd3cefc7691", "name": "v1cart10", "description": "Promotion", "sku": "sale2024", "slug": "", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": false, "unit_price": { "amount": -1000, "currency": "USD", "includes_tax": false }, "value": { "amount": -1000, "currency": "USD", "includes_tax": false }, "links": {}, "relationships": { "taxes": { "data": null }, "custom_discounts": { "data": null }, "promotions": { "data": [ { "type": "promotion", "id": "05b35539-7946-4145-a8ff-bfd3cefc7691" } ] } }, "meta": { "display_price": { "with_tax": { "unit": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" }, "value": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" } }, "without_tax": { "unit": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" }, "value": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "discount": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "without_discount": { "unit": { "amount": 0, "currency": "", "formatted": "0" }, "value": { "amount": 0, "currency": "", "formatted": "0" } } }, "timestamps": { "created_at": "2024-05-31T16:26:07Z", "updated_at": "2024-05-31T16:26:07Z" } } } ], "meta": { "display_price": { "with_tax": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "without_tax": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "tax": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "discount": { "amount": -4000, "currency": "USD", "formatted": "-$40.00" }, "without_discount": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "shipping": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2024-05-24T17:38:10Z", "updated_at": "2024-05-31T16:26:07Z", "expires_at": "2024-06-07T16:26:07Z" } }, "included": { "promotions": [ { "type": "promotion", "id": "05b35539-7946-4145-a8ff-bfd3cefc7691", "name": "v1cart10", "description": "v1cart10", "automatic": false, "promotion_type": "fixed_discount", "start": "2024-04-01T17:25:00Z", "end": "2024-06-01T17:25:03Z" }, { "type": "promotion", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44", "name": "cart20", "description": "cart20", "automatic": false, "promotion_source": "rule-promotion", "start": "2024-04-01T18:24:06Z", "end": "2024-06-01T18:24:09Z" }, { "type": "promotion", "id": "de19a043-a6da-4bde-b896-d17e16b77e25", "name": "item10", "description": "item10", "automatic": false, "promotion_source": "rule-promotion", "start": "2024-05-02T04:28:24Z", "end": "2024-06-02T04:28:28Z" } ] } } ``` ## `GET` Retrieve Promotions from an order ```http https://useast.api.elasticpath.com/v2/orders/:id?include=promotions` ``` ## Parameters ### Path parameters | Name | Required | Type | Description | |:-----|:---------|:---------|:---------------------| | `id` | Required | `string` | The ID of the order. | ### Query parameters | Name | Required | Type | Description | |:-----|:---------|:---------|:---------------------| | `include` | Required | `string` | The promotions included for the order. | ## Request Example -Curl ```bash curl -X GET https://useast.api.elasticpath.com/v2/orders/:id?include=promotions \ -H "Authorization: Bearer XXXX" ``` ## Response Example `200 OK` ```json { "data": { "id": "522dd525-38cb-4d25-9903-9d417b568096", "type": "order", "web_order_id": null, "status": "incomplete", "payment": "unpaid", "shipping": "unfulfilled", "anonymized": false, "customer": { "name": "kevin", "email": "andy@example.com" }, "shipping_address": { "first_name": "Andy", "last_name": "Dwyer", "phone_number": "123-456-1111", "company_name": "Elasticpath", "line_1": "1 Sunny Street", "line_2": "", "city": "Sunny Town", "postcode": "v1v 1v1", "county": "BC", "country": "CA", "instructions": "" }, "billing_address": { "first_name": "Andy", "last_name": "Dwyer", "company_name": "Elasticpath", "line_1": "1 Sunny Street", "line_2": "", "city": "Sunny Town", "postcode": "v1v 1v1", "county": "BC", "country": "CA" }, "links": {}, "meta": { "display_price": { "with_tax": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "without_tax": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "tax": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "discount": { "amount": -4000, "currency": "USD", "formatted": "-$40.00" }, "balance_owing": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "paid": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "authorized": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "without_discount": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "shipping": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2024-05-31T16:43:31Z", "updated_at": "2024-05-31T16:43:31Z" } }, "relationships": { "items": { "data": [ { "type": "item", "id": "874aa011-c160-4819-8a87-7b54be25481b" }, { "type": "item", "id": "baf6e9f6-f248-477c-b508-3788957908cf" }, { "type": "item", "id": "58e6c654-fe32-4bdf-ae88-958c988fb1b3" } ] }, "promotions": { "data": [ { "type": "promotion", "id": "05b35539-7946-4145-a8ff-bfd3cefc7691" }, { "type": "promotion", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44" } ] } } }, "included": { "promotions": [ { "type": "promotion", "id": "05b35539-7946-4145-a8ff-bfd3cefc7691", "name": "v1cart10", "description": "v1cart10", "automatic": false, "promotion_type": "fixed_discount", "start": "2024-04-01T17:25:00Z", "end": "2024-06-01T17:25:03Z" }, { "type": "promotion", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44", "name": "cart20", "description": "cart20", "automatic": false, "promotion_source": "rule-promotion", "start": "2024-04-01T18:24:06Z", "end": "2024-06-01T18:24:09Z" } ] } } ``` ## `GET` Retrieve Promotions from order items ```http https://useast.api.elasticpath.com/v2/orders/:id/items ``` ## Parameters ### Path parameters | Name | Required | Type | Description | | --- | --- | --- | --- | | `id` | Required | `string` | The ID of the order. | ### Headers | Name | Required | Type | Description | | --- | --- | --- |---------------------------------------------------------| | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | | `X-Moltin-Customer-Token` | Optional | `string` | A customer token to access a specific customer's order. | ### Query parameters | Name | Required | Type | Description | |:----------|:---------|:---------|:-------------------------------------------| | `include` | Optional | `string` | The promotions for order items. | ## Request Example - Curl ```bash curl -X GET https://useast.api.elasticpath.com/v2/orders/:id/items?include=promotions \ -H "Authorization: Bearer XXXX" ``` ## Response Example The following response example shows `included` object containing both order-level and item-level promotions. `200 OK` ```json { "data": [ { "id": "874aa011-c160-4819-8a87-7b54be25481b", "type": "order_item", "custom_field_test": null, "tracking_number": null, "quantity": 1, "product_id": "05b35539-7946-4145-a8ff-bfd3cefc7691", "name": "v1cart10", "sku": "sale2024", "unit_price": { "amount": -1000, "currency": "USD", "includes_tax": false }, "value": { "amount": -1000, "currency": "USD", "includes_tax": false }, "links": {}, "meta": { "display_price": { "with_tax": { "unit": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" }, "value": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" } }, "without_tax": { "unit": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" }, "value": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "discount": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "without_discount": { "unit": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" }, "value": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" } } }, "timestamps": { "created_at": "2024-05-31T16:43:31Z", "updated_at": "2024-05-31T16:43:31Z" } }, "relationships": { "cart_item": { "data": { "type": "cart_item", "id": "6d55f4b1-2869-4b31-a214-0cbe11ac6722" } }, "promotions": { "data": [ { "type": "promotion", "id": "05b35539-7946-4145-a8ff-bfd3cefc7691" } ] } } }, { "id": "baf6e9f6-f248-477c-b508-3788957908cf", "type": "promotion_item", "custom_field_test": null, "tracking_number": null, "quantity": 1, "product_id": "e4d929d5-f471-4317-9a86-a84a6c572b44", "name": "cart20", "sku": "sale2024", "unit_price": { "amount": -2000, "currency": "USD", "includes_tax": false }, "value": { "amount": -2000, "currency": "USD", "includes_tax": false }, "links": {}, "meta": { "display_price": { "with_tax": { "unit": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" }, "value": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" } }, "without_tax": { "unit": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" }, "value": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "discount": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "without_discount": { "unit": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" }, "value": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" } } }, "timestamps": { "created_at": "2024-05-31T16:43:31Z", "updated_at": "2024-05-31T16:43:31Z" } }, "relationships": { "cart_item": { "data": { "type": "cart_item", "id": "614d4801-5077-468d-9514-db81306d1560" } }, "promotions": { "data": [ { "type": "promotion", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44" } ] } }, "promotion_source": "rule-promotion" }, { "id": "58e6c654-fe32-4bdf-ae88-958c988fb1b3", "type": "order_item", "custom_field_test": null, "tracking_number": null, "quantity": 1, "product_id": "5a4662d2-9a2b-4f6e-a215-2970db914b0c", "name": "sku1", "sku": "sku1", "unit_price": { "amount": 10000, "currency": "USD", "includes_tax": false }, "value": { "amount": 10000, "currency": "USD", "includes_tax": false }, "discounts": [ { "amount": { "amount": -2000, "currency": "USD", "includes_tax": false }, "code": "sale2024", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44", "promotion_source": "rule-promotion", "is_cart_discount": true }, { "amount": { "amount": -1000, "currency": "USD", "includes_tax": false }, "code": "sale2024", "id": "de19a043-a6da-4bde-b896-d17e16b77e25", "promotion_source": "rule-promotion" } ], "links": {}, "meta": { "display_price": { "with_tax": { "unit": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "value": { "amount": 6000, "currency": "USD", "formatted": "$60.00" } }, "without_tax": { "unit": { "amount": 6000, "currency": "USD", "formatted": "$60.00" }, "value": { "amount": 6000, "currency": "USD", "formatted": "$60.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "discount": { "unit": { "amount": -4000, "currency": "USD", "formatted": "-$40.00" }, "value": { "amount": -4000, "currency": "USD", "formatted": "-$40.00" } }, "without_discount": { "unit": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "value": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } }, "discounts": { "sale2024": { "amount": -3000, "currency": "USD", "formatted": "-$30.00", "constituents": { "de19a043-a6da-4bde-b896-d17e16b77e25": { "amount": -1000, "currency": "USD", "formatted": "-$10.00" }, "e4d929d5-f471-4317-9a86-a84a6c572b44": { "amount": -2000, "currency": "USD", "formatted": "-$20.00" } } } } }, "timestamps": { "created_at": "2024-05-31T16:43:31Z", "updated_at": "2024-05-31T16:43:31Z" } }, "relationships": { "cart_item": { "data": { "type": "cart_item", "id": "2745400a-39f5-4b7b-ae77-c84b2ca1a723" } }, "promotions": { "data": [ { "type": "promotion", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44" }, { "type": "promotion", "id": "de19a043-a6da-4bde-b896-d17e16b77e25" } ] } }, "catalog_id": "09b9359f-897f-407f-89a2-702e167fe781", "catalog_source": "pim" } ], "included": { "promotions": [ { "type": "promotion", "id": "05b35539-7946-4145-a8ff-bfd3cefc7691", "name": "v1cart10", "description": "v1cart10", "automatic": false, "promotion_type": "fixed_discount", "start": "2024-04-01T17:25:00Z", "end": "2024-06-01T17:25:03Z" }, { "type": "promotion", "id": "e4d929d5-f471-4317-9a86-a84a6c572b44", "name": "cart20", "description": "cart20", "automatic": false, "promotion_source": "rule-promotion", "start": "2024-04-01T18:24:06Z", "end": "2024-06-01T18:24:09Z" }, { "type": "promotion", "id": "de19a043-a6da-4bde-b896-d17e16b77e25", "name": "item10", "description": "item10", "automatic": false, "promotion_source": "rule-promotion", "start": "2024-05-02T04:28:24Z", "end": "2024-06-02T04:28:28Z" } ] } } ``` --- ## Bulk Add Items to Cart The bulk add feature allows shoppers to add an array of items to their cart in one action, rather than adding each item one at a time. Shoppers can choose to add items using either the SKU or product ID. Additionally, they can also include quantity and shipping group details in bulk requests. This minimizes the time for shoppers while adding items to their cart. Shoppers can even add multiple items with the same or different shipping groups to their cart. When you add multiple items that qualify for free gifts to the cart, the corresponding free gifts for all eligible products are also automatically added to the cart. An example for bulk add is: ```json { "data": [ { "type": "cart_item", "sku": "sku-1", "quantity": 1 }, { "type": "cart_item", "sku": "sku-2", "quantity": 1 } ], "options": { "add_all_or_nothing": true } } ``` With the bulk add items to cart capability, you can use one or more of the following cart actions in a transaction: - [Add Product to Cart](/docs/api/carts/manage-carts#add-product-to-cart) - [Add Custom Item to Cart](/docs/api/carts/manage-carts#add-custom-item-to-cart) - [Add Promotion to Cart](/docs/api/carts/manage-carts#add-promotion-to-cart) :::caution The request body depends on the type of items that you want to add, such as promotion, custom or product. ::: ## Dynamic Bundles A bundle is a purchasable product that is composed of a combination of two or more products that you want to sell together. You can create multiple components within a bundle. Each component can have one or more options. Each option is a product and a quantity. You can configure minimum and/or maximum values for the number of product options in a component that your shoppers can select. For example, you can enable a shopper to select 1 or more product options from a list of 10. These are called [dynamic bundles](/docs/api/pxm/products/products#dynamic-bundles). Your dynamic bundles are displayed in your published catalogs. Shoppers make their selections. A shoppers selections are stored in the [configure a shopper bundle](/docs/api/pxm/catalog/configure-by-context-product) endpoint. The shoppers selections are stored in a `bundle_configuration` which is supplied in the `add product to cart` request. ```json "bundle_configuration": { "selected_options": { "games": { "d7b79eb8-19d8-45ea-86ed-2324a604dd9c": 1 }, "toys": { "0192ccdd-6d33-4898-87d7-c4d87f2bf8ea": 1, "1aea6f97-f0d9-452c-b3c1-7fb5629ead82": 1 } } } ``` When a cart is checked out, the options a shopper selected are added to the order. See [order items](/docs/api/carts/get-order-items). ## Personalized Products You can allow your shoppers to add custom text to a product when adding product items to their carts. This is useful, for example, if you have a product like a T-shirt that can be personalized. You can do this using the `custom_inputs` attribute. The `custom_inputs` attribute must be an object. For example, you sell greetings cards that can be printed with your shoppers personalized messages. Once you have defined your custom inputs on a product, you must configure the custom inputs in your orders. For example, a birthday card may have custom inputs for name and message defined for a product. ```json { "custom_inputs": { "name": { "name": "Name", "validation_rules": { "type": "string" }, "message": { "name": "Message", "validation_rules": { "type": "string" } } } } } ``` When the product is added to the cart, those custom inputs are supplied. ```json { "custom_inputs": { "name": { "name": "Fred", "message": "Happy Birthday" } } } ``` If the same product has different `custom_inputs` attributes, then these are added as separate items in a cart. The `custom_inputs` attribute is stored in the cart item and must not exceed 1MB. When a cart is [checked out](/docs/api/carts/checkout), the `custom_inputs` attribute becomes part of the [order](/docs/api/carts/get-an-order) items. When you add products to a cart with `custom_inputs`, there are certain limitations on usage of the `custom_inputs` with the following promotion types: - For [Free Gift Promotions](/docs/api/promotions/create-a-promotion#request), you can add `custom_inputs` to gift items. - For [Fixed Bundle Discount Promotions](/docs/api/promotions/create-a-promotion#request), the promotion applies as long as the cart contains the bundle SKUs even when there are different `custom_inputs`. - For [X for Y Discount Promotion](/docs/api/promotions/create-a-promotion#request) and [X for amount discount promotion](/docs/api/promotions/create-a-promotion#request), the promotion applies when there are two SKUs with the same `custom_inputs`. The promotion does not apply when there are different `custom_inputs` and the SKUs are in different line items. ## `POST` Bulk Add to Cart ```text https://useast.api.elasticpath.com/v2/carts/:id/items ``` ## Parameters ### Path parameters | Name | Required | Type | Description | |:------------|:---------|:---------|:-----------------------------------------| | `id` | Required | `string` | The unique identifier of the cart that you created. | ### Headers | Name | Required | Type | Description | |:--------------------------|:---------|:---------|:---------------------------| | `X-MOLTIN-CURRENCY` | Optional | `string` | Specifies the currency to be used for the products in the cart. If you do not specify a currency, the site’s default currency is used. This header only affects the first item added to the cart. | | `Authorization` | Required | `string` | The Bearer token to grant access to the API. | | `X-Moltin-Customer-Token` | Required | `string` | The unique identifier of a signed-in customer. Corresponds to the `customer_ids` attribute in a `catalog_rule` object. | | `EP-Channel` | Required | `string` | The channel, such as website or mobile app. Corresponds to the `channel` attribute in a `catalog_rule` object. | | `EP-Context-Tag` | Required | `string` | A tag defined in the store, such as `clearance`. Corresponds to the `tag` attribute in a `catalog_rule` object. | ### Body | Name | Required | Type | Description | |:-----------------------------|:---------|:----------|:-----------------------| | `options.add_all_or_nothing` | Optional | `boolean` | When `true`, if an error occurs for any item, no items are added in the cart. When `false`, valid items are added in the cart and the items with errors are reported in the response. Default is `true`. | #### Custom item body | Name | Required | Type | Description | |:---------------------|:---------|:----------|:-------------------------------| | `type` | Required | `string` | The type of item, such as `custom_item`. | | `name` | Required | `string` | Specifies the name of the item. | | `sku` | Required | `string` | The SKU of the item. | | `description` | Optional | `string` | Specifies the description of the item. | | `quantity` | Required | `integer` | Specifies the amount of items to add to the cart. | | `price.amount` | Required | `integer` | The price of the items. | | `price.includes_tax` | Optional | `boolean` | If true, the price includes tax. The default is true. | | `amount` | Required | `integer` | Specifies the total cost of the items added to the cart. | | `tax` | Optional | `array` | Specifies a list of tax items to apply to the cart item. **Note**: Only administrators with client credentials can use this field. | | `custom_inputs` | Optional | `object` | The custom text to be added to a product. See [custom_inputs](/docs/api/pxm/products/create-product#personalizing-products). | | `shipping_group_id` | Optional | `string` | The shipping group ID to be added. See [Get a Cart Shipping Group by ID](/docs/ship-groups/shipping-groups/shipping-groups-api/get-a-cart-shipping-group-by-id). | #### Cart item body | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `type` | Required | `string` | Specifies the type, such as `cart_item`. | | `id` | Required | `string` | Specifies the ID of the item that you want to add to cart. **Note**: Ensure that you select only one of the two options, by SKU or by product id. | | `sku` | Required | `string` | Specifies the item SKU that you want to add to cart. **Note**: Ensure that you select only one of the two options, by SKU or by product id. | | `custom_inputs` | Optional | `object` | The custom text to be added to a product. See [custom_inputs](/docs/api/pxm/products/create-product#personalizing-products) | | `shipping_group_id` | Optional | `string` | The shipping group ID to be added. See [Get a Cart Shipping Group by ID](/docs/ship-groups/shipping-groups/shipping-groups-api/get-a-cart-shipping-group-by-id). | #### Promotion item body | Name | Required | Type | Description | |:-------|:---------|:---------|:----------------------------------------------| | `type` | Required | `string` | Specifies the promotional item, such as `promotion_item`. | | `code` | Required | `string` | Specifies the code for the promotional item, such as `promoCode`. | ## Request Example - Product ID ### Curl ```json curl -X POST https://useast.api.elasticpath.com//v2/carts/:id/items \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -H "X-Moltin-Customer-Token: XXXX" \ -d $ { "data": [ { "type": "custom_item", "name": "My Custom Item", "sku": "my-custom-item", "description": "My first custom item!", "custom_inputs": { "personalization": "My personal message" }, "quantity": 1, "price": { "amount": 20000, "includes_tax": true } }, { "type": "cart_item", "id": "838520de-b64a-4a0e-9d4c-f5bb53c83ec3", "quantity": 1 }, { "type": "promotion_item", "code": "5off" } ], "options": { "add_all_or_nothing": true } } ``` #### JavaScript SDK ```javascript const reference = "XXXX"; const items = [ { type: "custom_item", name: "My Custom Item", sku: "my-custom-item", description: "My first custom item!", quantity: 1, price: { amount: 20000, includes_tax: true, }, }, { type: "cart_item", id: "838520de-b64a-4a0e-9d4c-f5bb53c83ec3", quantity: 1, }, { type: "promotion_item", code: "5off", }, ]; // Where `EPCC` is an authenticated client await EPCC.Cart(reference).BulkAdd(items); ``` ## Response Example - Product ID `201 Created` ```json { "data": [ { "id": "931dcd00-7621-4bb6-95bb-12fc58b10d7d", "type": "custom_item", "name": "My Custom Item", "description": "My first custom item!", "sku": "my-custom-item", "slug": "", "custom_inputs": { "personalization": "My personal message" }, "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": false, "unit_price": { "amount": 20000, "currency": "USD", "includes_tax": true }, "value": { "amount": 20000, "currency": "USD", "includes_tax": true }, "links": {}, "meta": { "display_price": { "with_tax": { "unit": { "amount": 20000, "currency": "USD", "formatted": "$200.00" }, "value": { "amount": 20000, "currency": "USD", "formatted": "$200.00" } }, "without_tax": { "unit": { "amount": 20000, "currency": "USD", "formatted": "$200.00" }, "value": { "amount": 20000, "currency": "USD", "formatted": "$200.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } } }, "timestamps": { "created_at": "2020-08-27T15:33:49Z", "updated_at": "2020-08-27T15:33:49Z" }, "catalog_id": "92073438-7640-4ace-9670-c8c5c1a89cd7", "catalog_source": "pim" } }, { "id": "2e5ad28c-e112-4a43-a148-37ce842f49c0", "type": "cart_item", "product_id": "838520de-b64a-4a0e-9d4c-f5bb53c83ec3", "name": "Item Name", "description": "item description", "sku": "item_sku", "slug": "item_slug", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": false, "unit_price": { "amount": 5000, "currency": "USD", "includes_tax": false }, "value": { "amount": 5000, "currency": "USD", "includes_tax": false }, "links": { "product": "https://useast.api.elasticpath.com/v2/products/838520de-b64a-4a0e-9d4c-f5bb53c83ec3" }, "meta": { "display_price": { "with_tax": { "unit": { "amount": 5000, "currency": "USD", "formatted": "$50.00" }, "value": { "amount": 5000, "currency": "USD", "formatted": "$50.00" } }, "without_tax": { "unit": { "amount": 5000, "currency": "USD", "formatted": "$50.00" }, "value": { "amount": 5000, "currency": "USD", "formatted": "$50.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } } }, "timestamps": { "created_at": "2020-08-27T15:33:49Z", "updated_at": "2020-08-27T15:33:49Z" } }, "catalog_id": "92073438-7640-4ace-9670-c8c5c1a89cd7", "catalog_source": "pim" }, { "id": "1425513e-8446-4e84-a72b-8e77d47f906f", "type": "promotion_item", "promotion_id": "38ef7ac1-2066-4507-90c9-2de4b49d3717", "name": "$5 off", "description": "Promotion", "sku": "5off", "slug": "", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": false, "unit_price": { "amount": -500, "currency": "USD", "includes_tax": false }, "value": { "amount": -500, "currency": "USD", "includes_tax": false }, "links": {}, "meta": { "display_price": { "with_tax": { "unit": { "amount": -500, "currency": "USD", "formatted": "-$5.00" }, "value": { "amount": -500, "currency": "USD", "formatted": "-$5.00" } }, "without_tax": { "unit": { "amount": -500, "currency": "USD", "formatted": "-$5.00" }, "value": { "amount": -500, "currency": "USD", "formatted": "-$5.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } } }, "timestamps": { "created_at": "2020-08-27T15:33:49Z", "updated_at": "2020-08-27T15:33:49Z" } }, "catalog_id": "92073438-7640-4ace-9670-c8c5c1a89cd7", "catalog_source": "pim" } ], "meta": { "display_price": { "with_tax": { "amount": 24500, "currency": "USD", "formatted": "$245.00" }, "without_tax": { "amount": 24500, "currency": "USD", "formatted": "$245.00" }, "tax": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2020-08-27T15:33:49Z", "updated_at": "2020-08-27T15:33:49Z" }, "messages": [ { "source": { "type": "promotion_item", "id": "1425513e-8446-4e84-a72b-8e77d47f906f" }, "title": "Promotion Added", "description": "Promotion has been added to cart." } ] } } ``` ## Request Example - SKU ```json { "data": [ { "type": "cart_item", "sku": "sku-1", "quantity": 1 }, { "type": "cart_item", "sku": "sku-2", "quantity": 1 } ], "options": { "add_all_or_nothing": true } } ``` ## Response Example - SKU `201 Created` ```json { "data": [ { "id": "0ac4ee19-7d8e-4b2f-b087-e4073ec801a4", "type": "cart_item", "product_id": "6648dde1-f7c1-4e77-9698-1fd541d121af", "name": "Product Name", "description": "description", "sku": "sku-1", "slug": "1", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": true, "unit_price": { "amount": 11, "currency": "USD", "includes_tax": true }, "value": { "amount": 11, "currency": "USD", "includes_tax": true }, "links": { "product": "https://useast.api.elasticpath.com/v2/products/6648dde1-f7c1-4e77-9698-1fd541d121af" }, "meta": { "display_price": { "with_tax": { "unit": { "amount": 11, "currency": "USD", "formatted": "$0.11" }, "value": { "amount": 11, "currency": "USD", "formatted": "$0.11" } }, "without_tax": { "unit": { "amount": 11, "currency": "USD", "formatted": "$0.11" }, "value": { "amount": 11, "currency": "USD", "formatted": "$0.11" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } } }, "timestamps": { "created_at": "2020-10-23T23:15:24Z", "updated_at": "2020-10-23T23:15:24Z" } }, "catalog_id": "92073438-7640-4ace-9670-c8c5c1a89cd7", "catalog_source": "pim" }, { "id": "18c23ab3-92e5-4671-9c28-fbfcc8f7db18", "type": "cart_item", "product_id": "acede2a9-f763-453a-a3ae-cc4f66e6dca3", "name": "Product Name 2", "description": "Description 2", "sku": "sku-2", "slug": "2", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": true, "unit_price": { "amount": 22, "currency": "USD", "includes_tax": true }, "value": { "amount": 22, "currency": "USD", "includes_tax": true }, "links": { "product": "https://useast.api.elasticpath.com/v2/products/acede2a9-f763-453a-a3ae-cc4f66e6dca3" }, "meta": { "display_price": { "with_tax": { "unit": { "amount": 22, "currency": "USD", "formatted": "$0.22" }, "value": { "amount": 22, "currency": "USD", "formatted": "$0.22" } }, "without_tax": { "unit": { "amount": 22, "currency": "USD", "formatted": "$0.22" }, "value": { "amount": 22, "currency": "USD", "formatted": "$0.22" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } } }, "timestamps": { "created_at": "2020-10-23T23:15:24Z", "updated_at": "2020-10-23T23:15:24Z" } }, "catalog_id": "92073438-7640-4ace-9670-c8c5c1a89cd7", "catalog_source": "pim" } ], "meta": { "display_price": { "with_tax": { "amount": 33, "currency": "USD", "formatted": "$0.33" }, "without_tax": { "amount": 33, "currency": "USD", "formatted": "$0.33" }, "tax": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2020-10-23T23:15:24Z", "updated_at": "2020-10-23T23:15:24Z" } } } ``` ## Request Example - Add items with shipping groups ```bash curl -X POST https://useast.api.elasticpath.com/v2/carts/:id/items \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $'{ "data": [ { "type": "cart_item", "sku": "sku1", "quantity": 1, "shipping_group_id": "cc63b873-4eff-450c-86d2-ec255160ba2e" }, { "type": "cart_item", "sku": "sku2", "quantity": 1, "shipping_group_id": "5b37d927-e19f-4477-89f8-f18c2841e629" } ], "options": { "add_all_or_nothing": false } } ``` ## Response Example - Add items with shipping groups `201 Created` ```json { "data": [ { "id": "564c710b-695e-46e4-a4cb-54114f4ec604", "type": "cart_item", "product_id": "5ed105c9-112d-4a9d-87b7-e08dcc797b0b", "name": "sku1", "description": "sku1", "sku": "sku1", "slug": "sku1", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": false, "unit_price": { "amount": 10000, "currency": "USD", "includes_tax": false }, "value": { "amount": 10000, "currency": "USD", "includes_tax": false }, "links": { "product": "https://useast.api.elasticpath.com/v2/products/5ed105c9-112d-4a9d-87b7-e08dcc797b0b" }, "meta": { "display_price": { "with_tax": { "unit": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "value": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } }, "without_tax": { "unit": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "value": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "discount": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "without_discount": { "unit": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "value": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } } }, "timestamps": { "created_at": "2023-06-29T16:50:07Z", "updated_at": "2023-06-29T16:50:07Z" } }, "catalog_id": "c1a94a13-ca0d-4793-982a-a55e77a9f9ff", "catalog_source": "pim", "shipping_group_id": "cc63b873-4eff-450c-86d2-ec255160ba2e" }, { "id": "4089e7e2-4727-4322-a767-2a8493897887", "type": "cart_item", "product_id": "a0bb6fad-5fe6-4831-b731-91cc582bcf97", "name": "sku2", "description": "sku2", "sku": "sku2", "slug": "sku2", "image": { "mime_type": "", "file_name": "", "href": "" }, "quantity": 1, "manage_stock": false, "unit_price": { "amount": 10000, "currency": "USD", "includes_tax": false }, "value": { "amount": 10000, "currency": "USD", "includes_tax": false }, "links": { "product": "https://useast.api.elasticpath.com/v2/products/a0bb6fad-5fe6-4831-b731-91cc582bcf97" }, "meta": { "display_price": { "with_tax": { "unit": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "value": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } }, "without_tax": { "unit": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "value": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } }, "tax": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "discount": { "unit": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "value": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "without_discount": { "unit": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "value": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } } }, "timestamps": { "created_at": "2023-06-29T16:50:07Z", "updated_at": "2023-06-29T16:50:07Z" } }, "catalog_id": "c1a94a13-ca0d-4793-982a-a55e77a9f9ff", "catalog_source": "pim", "shipping_group_id": "5b37d927-e19f-4477-89f8-f18c2841e629" } ], "meta": { "display_price": { "with_tax": { "amount": 21000, "currency": "USD", "formatted": "$210.00" }, "without_tax": { "amount": 21000, "currency": "USD", "formatted": "$210.00" }, "tax": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "discount": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "without_discount": { "amount": 21000, "currency": "USD", "formatted": "$210.00" }, "shipping": { "amount": 1000, "currency": "USD", "formatted": "$10.00" } }, "timestamps": { "created_at": "2023-06-29T16:50:07Z", "updated_at": "2023-06-29T16:50:07Z", "expires_at": "2023-07-06T16:50:07Z" } } } ``` ## Request Examples ### Product ID - Curl ```bash curl -X POST https://useast.api.elasticpath.com/v2/carts/:id/items \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $'{ "data": [ { "type": "custom_item", "name": "My Custom Item", "sku": "my-custom-item", "description": "My first custom item!", "quantity": 1, "price": { "amount": 20000, "includes_tax": true } }, { "type": "cart_item", "id": "838520de-b64a-4a0e-9d4c-f5bb53c83ec3", "quantity": 1 }, { "type": "promotion_item", "code": "5off" } ], "options": { "add_all_or_nothing": true } }' ``` ### SKU - Curl ```bash curl -X POST https://useast.api.elasticpath.com/v2/carts/:reference/items \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $'{ "data": [ { "type": "custom_item", "name": "My Custom Item", "sku": "my-custom-item", "description": "My first custom item!", "quantity": 1, "price": { "amount": 20000, "includes_tax": true } }, { "type": "cart_item", "sku": "sku-1", "quantity": 1 }, { "type": "promotion_item", "code": "5off" } ], "options": { "add_all_or_nothing": true } }' ``` ### Bundle - Curl ```bash curl -X POST https://useast.api.elasticpath.com/v2/carts/:id/items \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $'{ "data": { "id": "5ab67bb3-b2c3-4348-af33-e370bd39b0c9", "type": "cart_item", "quantity": 1, "bundle_configuration": { "selected_options": { "tshirt": { "23759a57-13c1-4887-9ec2-fb47444751bd": 1 }, "comics": { "c7bcf7fd-1fab-4635-8ae0-7f187a9dbbce": 1, "d9768b40-cf28-406e-bafc-a6d130627eca": 1 } } } } }' ``` ## Response Example ```json { "data": { "id": "5ab67bb3-b2c3-4348-af33-e370bd39b0c9", "type": "product", "attributes": { "name": "T-shirt and comics", "description": "A t-shirt and two comics", "components": { "tshirt": { "name": "T-shirt", "options": [ { "id": "23759a57-13c1-4887-9ec2-fb47444751bd", "quantity": 1, "type": "product" }, { "id": "ffb9024e-82ce-49f8-b2a1-95ce0a452056", "quantity": 1, "type": "product" } ] }, "comics": { "name": "Comics", "minimum": 2, "maximum": 2, "options": [ { "id": "c7bcf7fd-1fab-4635-8ae0-7f187a9dbbce", "quantity": 1, "type": "product" }, { "id": "d9768b40-cf28-406e-bafc-a6d130627eca", "quantity": 1, "type": "product" }, { "id": "623b47ee-f43b-45ab-8939-cc6269c323ec", "quantity": 1, "type": "product" }, { "id": "bfdf583d-aad8-4b5c-879a-06d8f4304988", "quantity": 1, "type": "product" } ] } }, "price": { "USD": { "amount": 4000, "includes_tax": false } }, "sku": "tshcom", "published_at": "2022-02-28T16:40:39.731Z" }, "meta": { "bundle_configuration": { "selected_options": { "tshirt": { "23759a57-13c1-4887-9ec2-fb47444751bd": 1 }, "comics": { "c7bcf7fd-1fab-4635-8ae0-7f187a9dbbce": 1, "d9768b40-cf28-406e-bafc-a6d130627eca": 1 } } } } } } ``` ## Response Codes You might encounter the following response codes, depending on the scenario: - `400 Bad Request` - An error is found, such as insufficient available stock. - `404 Not found` - The requested product could not be found. :::note For items added in bulk, error codes are returned for each item individually in a response. ::: ### Bulk add error example `404 Not Found` ```json { "errors": [ { "status": 404, "title": "Product not found", "detail": "The requested product could not be found", "meta": { "sku": "sku-1" } }, { "status": 400, "title": "Insufficient stock", "detail": "There is not enough stock to add Product 2 to your cart", "meta": { "id": "91b074df-2b2a-44ff-be2d-fdb4fa2ddfb4", "sku": "sku-2" } } ] } ``` --- ## Capture a Transaction(Carts-orders) ## `POST` Capture a Transaction ```http https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/capture ``` Use this endpoint to capture a previously authorized payment. In this step, you can also pass in a custom reference, such as the payment reference from your chosen gateway. ## Parameters ### Path parameters | Name | Required | Type | Description | | --- | --- | --- | --- | | `transactionId` | Required | `string` | The UUID of the transaction to capture. | | `orderId` | Required | `string` | The UUID of the order. | ### Headers | Name | Required | Type | Description | | --- | --- | --- | --- | | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | ### Body | Name | Required | Type | Description | | --- | --- | --- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `custom_reference` | Optional | `string` | A custom reference that you can use to identify this transaction. If the value is different from original transaction, it will be overwritten by this value. Empty string value will clear the original value. If you omit this field in the request, the original value from the previous transaction will still persist. | ## Request Example ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transaction_id/capture \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $ { "data": { "custom_reference": "my_custom_reference" } } ``` ## Response Example `200 OK` ```json { "data": { "id": "bcafac29-c8ca-4293-822c-d1213e085c7c", "type": "transaction", "reference": "manual", "custom_reference": "my_custom_reference", "gateway": "manual", "amount": 60000, "currency": "GBP", "transaction_type": "capture", "status": "complete", "relationships": { "order": { "data": { "type": "order", "id": "239f104c-0b56-433c-a5f8-b73349196269" } } }, "meta": { "display_price": { "amount": 60000, "currency": "GBP", "formatted": "£600.00" }, "timestamps": { "created_at": "2020-02-17T13:24:42Z", "updated_at": "2020-02-17T13:24:45Z" } } } } ``` ## `POST` Capture a Transaction - Manual Use this endpoint to manually capture a previously authorized payment. ```http https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/capture ``` ## Parameters ### Path parameters | Name | Required | Type | Description | | --- | --- | --- | --- | | `transactionId` | Required | `string` | The UUID of the transaction to capture. | | `orderId` | Required | `string` | The UUID of the order. | ### Headers | Name | Required | Type | Description | | --- | --- | --- | --- | | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | ### Body | Name | Required | Type | Description | | --- | --- | --- | --- | | `capture_mechanism` | Required | `string` | Always `manual`. | ## Request Example ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transaction_id/capture \ -H "Authorization: Bearer XXXX" '{ "data": { "capture_mechanism": "manual" } }' ``` ## Response Example `200 OK` ```Json { "data": { "id": "09cf2557-ac72-46c4-8c66-243d065266e8", "type": "transaction", "reference": "pi_3MXQWxS5fsvVtlID1w1SejAP", "gateway": "elastic_path_payments_stripe", "amount": 20000, "refunded_amount": 0, "capture_mechanism": "manual", "currency": "USD", "transaction_type": "capture", "status": "complete", "relationships": { "order": { "data": { "type": "order", "id": "37e8325e-dd2d-48ff-9e1c-3ab82871a893" } } }, "meta": { "display_price": { "amount": 20000, "currency": "USD", "formatted": "$200.00" }, "display_refunded_amount": { "total": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2023-02-03T14:46:23Z", "updated_at": "2023-02-03T14:46:47Z" } } } } ``` ## Errors If you manually capture an authorized transaction, you can manually mark a transaction as refunded. Therefore, you cannot perform automatic refund. The following error response is returned if you perform automatic refund: ```Json { "errors": [ { "status": 400, "title": "Error while refunding", "detail": "Unable to automatically refund a manually capture transaction " } ] } ``` When you capture a transaction that was authorized but expired, the following error response example is returned from Stripe: ```json { "errors": [ { "status": 400, "title": "Payment gateway processing failed", "detail": "This PaymentIntent could not be captured because it has a status of canceled. Only a PaymentIntent with one of the following statuses may be captured: requires_capture.", "meta": { "error": { "code": "payment_intent_unexpected_state", "doc_url": "https://stripe.com/docs/error-codes/payment-intent-unexpected-state", "message": "This PaymentIntent could not be captured because it has a status of canceled. Only a PaymentIntent with one of the following statuses may be captured: requires_capture.", "payment_intent": { "amount": 10000, "amount_capturable": 0, "amount_details": { "tip": {} }, "amount_received": 0, "application": "ca_XXXXXXXXXXXXXXXXX", "application_fee_amount": null, "automatic_payment_methods": null, "canceled_at": 1678903544, "cancellation_reason": "automatic", "capture_method": "manual", "charges": { "data": [ { "amount": 10000, "amount_captured": 0, "amount_refunded": 10000, "application": "ca_XXXXXXXXXXXXXXXXXXXXXX", "application_fee": null, "application_fee_amount": null, "balance_transaction": null, "billing_details": { "address": { "city": null, "country": null, "line1": null, "line2": null, "postal_code": null, "state": null }, "email": null, "name": null, "phone": null }, "calculated_statement_descriptor": "BRITISH COLUMBIA", "captured": false, "created": 1678298743, "currency": "usd", "customer": null, "description": null, "destination": null, "dispute": null, "disputed": false, "failure_balance_transaction": null, "failure_code": null, "failure_message": null, "fraud_details": {}, "id": "ch_XXXXXXXXXXXXXXXXXXXXXXX", "invoice": null, "livemode": false, "metadata": { "email": "andy@example.com", "ip_address": "206.116.129.195", "order_id": "bb4e20d2-c691-45ba-9194-3b56889a8a89" }, "object": "charge", "on_behalf_of": null, "order": null, "outcome": { "network_status": "approved_by_network", "reason": null, "risk_level": "normal", "risk_score": 28, "seller_message": "Payment complete.", "type": "authorized" }, "paid": true, "payment_intent": "pi_XXXXXXXXXXXXXXXXX", "payment_method": "pm_XXXXXXXXXXXXXXXXX", "payment_method_details": { "card": { "brand": "visa", "checks": { "address_line1_check": null, "address_postal_code_check": null, "cvc_check": null }, "country": "US", "exp_month": 3, "exp_year": 2024, "fingerprint": "6EScLzf5uXxJBcOw", "funding": "credit", "installments": null, "last4": "4242", "mandate": null, "network": "visa", "three_d_secure": null, "wallet": null }, "type": "card" }, "receipt_email": "john@example.com", "receipt_number": null, "receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xS2pBaElTNUc2WWZHUlhZKKPN6KAGMgaEeIHxYGY6LBZTPB5PVZwD5OiKRdNSUpBHhCojSpNqWw1_S4FZfH8Apayi9bClrUzwHLCg", "refunded": true, "refunds": { "data": [ { "amount": 10000, "balance_transaction": null, "charge": "ch_XXXXXXXXXXXXXXXXX", "created": 1678903544, "currency": "usd", "id": "re_XXXXXXXXXXXXXXXXXXXXXXX", "metadata": {}, "object": "refund", "payment_intent": "pi_XXXXXXXXXXXXXXXXXXXXX", "reason": "expired_uncaptured_charge", "receipt_number": null, "source_transfer_reversal": null, "status": "succeeded", "transfer_reversal": null } ], "has_more": false, "object": "list", "total_count": 1, "url": "/v1/charges/ch_XXXXXXXXXXXXXXXXX/refunds" }, "review": null, "shipping": null, "source": null, "source_transfer": null, "statement_descriptor": null, "statement_descriptor_suffix": null, "status": "succeeded", "transfer_data": null, "transfer_group": null } ], "has_more": false, "object": "list", "total_count": 1, "url": "/v1/charges?payment_intent=pi_XXXXXXXXXXXXXXXXXXX" }, "client_secret": "pi_XXXXXXXXXXXXX_XXXXXXXXXXXXXXXXXXX", "confirmation_method": "automatic", "created": 1678298743, "currency": "usd", "customer": null, "description": null, "id": "pi_XXXXXXXXXXXXXXXXXXXX", "invoice": null, "last_payment_error": null, "latest_charge": "ch_XXXXXXXXXXXXXXXXXXX", "livemode": false, "metadata": { "email": "andy@example.com", "ip_address": "206.116.129.195", "order_id": "bb4e20d2-c691-45ba-9194-3b56889a8a89" }, "next_action": null, "object": "payment_intent", "on_behalf_of": null, "payment_method": "pm_XXXXXXXXXXXXXXXXX", "payment_method_options": { "card": { "installments": null, "mandate_options": null, "network": null, "request_three_d_secure": "automatic" } }, "payment_method_types": [ "card" ], "processing": null, "receipt_email": "john@example.com", "review": null, "setup_future_usage": null, "shipping": null, "source": null, "statement_descriptor": null, "statement_descriptor_suffix": null, "status": "canceled", "transfer_data": null, "transfer_group": null }, "request_log_url": "https://dashboard.stripe.com/acct_XXXXXXXXXXXX/test/logs/req_VQ55E6FnJYzKvT?t=1679435427", "type": "invalid_request_error" } } } ] } ``` When you capture a transaction that was authorized but expired, the following error response example is returned from Paypal: ```json { "errors": [ { "status": 422, "title": "Error received from paypal", "detail": "The requested action could not be performed, semantically incorrect, or failed business validation.", "meta": { "debug_id": "cf56b76ac5b8d", "details": { "description": "Authorization has expired.", "issue": "AUTHORIZATION_EXPIRED" }, "name": "UNPROCESSABLE_ENTITY" } } ] } ``` :::note You can cancel a transaction and initiate a new transaction to make the payment. The transaction status will remain `completed` until you [cancel a transaction](/docs/api/carts/cancel-a-transaction). ::: When you [GET a transaction](/docs/api/carts/get-a-transaction) that was authorized but expired, the following response is returned with `payment_details` and `next_actions`: ```json { "data": [ { "id": "f0336c18-33ac-4945-855d-f711f7da7477", "type": "transaction", "reference": "pi_XXXXXXXXXXXXXXXXX", "gateway": "elastic_path_payments_stripe", "amount": 10000, "refunded_amount": 0, "currency": "USD", "transaction_type": "authorize", "status": "complete", "relationships": { "order": { "data": { "type": "order", "id": "bb4e20d2-c691-45ba-9194-3b56889a8a89" } } }, "meta": { "display_price": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "display_refunded_amount": { "total": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2023-03-08T18:05:43Z", "updated_at": "2023-03-08T18:05:44Z" } }, "payment_details": { "detailed_status": "expired_uncaptured_charge" }, "next_actions": [ "cancel", "capture" ] } ] } ``` --- ## Configure Elastic Path Composable Commerce Stripe Plugin The Elastic Path Composable Commerce Stripe Plugin enables Commerce to securely connect to Stripe for payment capabilities. This plugin provides a more secure way to authenticate. If you are using Stripe or Stripe Intent gateway, you must install the Stripe plugin in your [Stripe Dashboard](https://dashboard.stripe.com/login). ## Steps to Configure Elastic Path Composable Commerce Stripe Plugin 1. Login to your [Stripe Dashboard](https://dashboard.stripe.com/login). 2. Ensure that you are in either a test mode or a production mode, depending on whether you are configuring a production environment or a test environment. You can switch the modes using the toggle in the top-right corner of the dashboard. 3. Install the Elastic Path Composable Commerce Stripe Plugin within the Stripe Dashboard. 4. Once installed, navigate to the **View App Settings**, and then select **View API Keys**. 5. Copy the **Publishable key** value. This key is used when configuring Payment Elements on your front-end. 6. Copy the **Secret key** value. Paste this key in Commerce Manager or Payment gateway APIs for [Stripe Payment Intents](/docs/commerce-manager/payments/configure-other-payment-gateways#enabling-stripe-payment-intents) gateways to make the payments. --- ## Confirm an Order ## `POST` Confirm an Order ```http https://useast.api.elasticpath.com/v2/orders/:orderID/confirm ``` Use this endpoint to confirm the stripe payment intent and synchronize it with Commerce Cloud. See [Cart Payment Intent](/docs/api/carts/create-cart-payment-intent). ## Parameters ### Path parameters | Name | Required | Type | Description | |:-----|:---------|:---------|:----------------------------------------| | `orderID` | Required | `string` | The ID of the order that you want to confirm. | ### Headers | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | ### Body | Name | Required | Type | Description | |:-------|:---------|:---------|:------------| | `options` | Optional | `object` | Defines various Stripe options, such as `order_id` and `statement_descriptor`, when confirming an order that is linked to a Payment Intent. Refer to [Stripe Documentation](https://stripe.com/docs/api/payment_intents) for additional available `options`. | | `options.metadata.order_id` | Optional | `string` | Represents the unique identifier of the order linked to the Payment Intent. | | `options.metadata.statement_descriptor` | Optional | `string` | Represents description of a charge on your shoppers statements. | ## Request Example ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderID/confirm \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $ { "data": { "options": { "metadata": { "order_id": "{{orderID}}", "statement_descriptor": "Confirmed intent" } } } } ``` ## Response Example ```json { "data": { "id": "33693acb-ef86-49b1-88ff-29ecdfad1e3e", "type": "transaction", "reference": "pi_xxxxxxxxxxxxxxxxxx", "name": "Stripe Payment Intent", "custom_reference": "pi_xxxxxxxxxxxxxxxxxx", "gateway": "elastic_path_payments_stripe", "amount": 10000, "refunded_amount": 0, "currency": "USD", "transaction_type": "authorize", "status": "pending", "relationships": { "order": { "data": { "type": "order", "id": "d99142c0-1bfb-407a-a4a6-ed0e7641cf9a" } } }, "meta": { "display_price": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "display_refunded_amount": { "total": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2024-01-08T21:43:08Z", "updated_at": "2024-01-08T21:43:08Z" } }, "payment_intent": { "amount": 10000, "amount_capturable": 0, "amount_details": { "tip": { "amount": 0 } }, "amount_received": 0, "application": { "deleted": false, "id": "ca_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "name": "", "object": "" }, "application_fee_amount": 0, "automatic_payment_methods": { "enabled": true }, "canceled_at": 0, "cancellation_reason": "", "capture_method": "manual", "charges": { "data": [], "has_more": false, "total_count": 0, "url": "/v1/charges?payment_intent=pi_xxxxxxxxxxxxxxxxxx" }, "client_secret": "pi_xxxxxxxxxxxxxxxxxx_secret_xxxxxxxxxxxxxxxxxx", "confirmation_method": "automatic", "created": 1704750178, "currency": "usd", "customer": null, "description": "", "id": "pi_xxxxxxxxxxxxxxxxxx", "invoice": null, "last_payment_error": null, "livemode": false, "metadata": { "order_id": "d99142c0-1bfb-407a-a4a6-ed0e7641cf9a", "statement_descriptor": "Confirmed intent" }, "next_action": null, "object": "payment_intent", "on_behalf_of": null, "payment_method": null, "payment_method_options": { "acss_debit": null, "affirm": null, "afterpay_clearpay": null, "alipay": null, "au_becs_debit": null, "bacs_debit": null, "bancontact": null, "blik": null, "boleto": null, "card": { "capture_method": "", "installments": null, "mandate_options": null, "network": "", "request_three_d_secure": "automatic", "setup_future_usage": "", "statement_descriptor_suffix_kana": "", "statement_descriptor_suffix_kanji": "" }, "card_present": null, "customer_balance": null, "eps": null, "fpx": null, "giropay": null, "grabpay": null, "ideal": null, "interac_present": null, "klarna": null, "konbini": null, "link": { "capture_method": "", "persistent_token": "", "setup_future_usage": "" }, "oxxo": null, "p24": null, "paynow": null, "promptpay": null, "sepa_debit": null, "sofort": null, "us_bank_account": null, "wechat_pay": null }, "payment_method_types": [ "card", "link" ], "processing": null, "receipt_email": "john@example.com", "review": null, "setup_future_usage": "", "shipping": null, "source": null, "statement_descriptor": "", "statement_descriptor_suffix": "", "status": "requires_payment_method", "transfer_data": null, "transfer_group": "" }, "payment_details": { "detailed_status": "requires_payment_method" }, "next_actions": [ "cancel" ] } } ``` --- ## Include for Custom Discounts ## `GET` Include Custom Discounts You can use `include=custom_discounts` to retrieve detailed information about the custom discounts associated with an order. ```http https://useast.api.elasticpath.com/v2/orders/:id?include=custom_discounts ``` ## Parameters ### Path parameters | Name | Required | Type | Description | |:-----|:---------|:---------|:---------------------| | `id` | Required | `string` | The ID of the order. | ### Query parameters | Name | Required | Type | Description | |:-----|:---------|:---------|:---------------------| | `include` | Required | `string` | The custom discounts for the order. | ## Request Example - Curl ```bash curl -X GET https://useast.api.elasticpath.com/v2/orders/:id?include=custom_discounts \ -H "Authorization: Bearer XXXX" ``` ## Response Example `200 OK` ```JSon { "data": { "id": "a51a680e-9570-4f8d-9bbc-bd3c9fcd9ea3", "type": "order", "status": "incomplete", "payment": "unpaid", "shipping": "unfulfilled", "anonymized": false, "customer": { "name": "John Doe", "email": "andy@example.com" }, "shipping_address": { "first_name": "Andy", "last_name": "Dwyer", "phone_number": "123-456-1111", "company_name": "Elasticpath", "line_1": "1 Sunny Street", "line_2": "", "city": "Sunny Town", "postcode": "v1v 1v1", "county": "BC", "country": "CA", "instructions": "" }, "billing_address": { "first_name": "Andy", "last_name": "Dwyer", "company_name": "Elasticpath", "line_1": "1 Sunny Street", "line_2": "", "city": "Sunny Town", "postcode": "v1v 1v1", "county": "BC", "country": "CA" }, "links": {}, "meta": { "display_price": { "with_tax": { "amount": 8500, "currency": "USD", "formatted": "$85.00" }, "without_tax": { "amount": 8500, "currency": "USD", "formatted": "$85.00" }, "tax": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "discount": { "amount": -1500, "currency": "USD", "formatted": "-$15.00" }, "balance_owing": { "amount": 8500, "currency": "USD", "formatted": "$85.00" }, "paid": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "authorized": { "amount": 0, "currency": "USD", "formatted": "$0.00" }, "without_discount": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } }, "timestamps": { "created_at": "2023-04-19T23:08:57Z", "updated_at": "2023-04-19T23:08:57Z" } }, "relationships": { "items": { "data": [ { "type": "item", "id": "8addeb0a-3117-4583-bb92-efd7a7aa91b5" } ] }, "custom_discounts": { "data": [ { "type": "custom_discount", "id": "4b3ec5f2-941f-4125-89d7-5885b3e9782b" } ] } } }, "included": { "custom_discounts": [ { "amount": { "amount": -500, "currency": "USD" }, "type": "custom_discount", "id": "3e36ad8e-cf3e-463d-8332-ef569ffc819c", "external_id": "item custom discount", "discount_engine": "Custom Discount Engine", "description": "custom discount description", "discount_code": "item custom-code" }, { "amount": { "amount": -1000, "currency": "USD" }, "type": "custom_discount", "id": "4b3ec5f2-941f-4125-89d7-5885b3e9782b", "external_id": "cart custom discount", "discount_engine": "Custom Discount Engine", "description": "custom discount description", "discount_code": "cart custom-code" } ] } } ``` --- ## Elastic Path Payments Powered by Stripe The Elastic Path Payments Powered by Stripe integration supports the following payment methods: - `authorize` - `capture` - `confirm` - `purchase` - `refund` :::note You can contact Elastic Path sales or [customer success team](mailto:customersuccess@elasticpath.com) to get more information about Elastic Path Payments powered by Stripe and to check whether it will work for you. ::: ## Authorization or Purchase - `POST` Pay using Token or Source ```http https://useast.api.elasticpath.com/v2/orders/:orderId/payments ``` ### Parameters #### Path parameters | Name | Required | Type | Description | |:----------|:---------|:---------|:-------------------------------------------| | `orderId` | Required | `string` | The universally unique identifier of the order that you want to pay for. | #### Headers | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | #### Body | Name | Required | Type | Description | |:--------------------------|:---------|:----------|:--------------------------| | `options.idempotency_key` | Optional | `string` | Provides the option to send a Stripe Idempotency Key. | | `options.receipt_email` | Optional | `string` | Provides the email address to which you want to send the Stripe receipts for the transactions within the store. This feature is available only in the live mode. | | `payment` | Required | `string` | Specifies the Stripe token or source. | | `options.customer` | Optional | `string` | Specifies the Stripe customer ID. This is required if you want to send a [source](https://stripe.com/docs/api/sources). | | `method` | Required | `string` | Specifies the transaction method, such as `purchase` or `authorize`. | | `amount` | Optional | `integer` | Specifies the amount to be paid for the transaction. | | `gateway` | Required | `string` | Specifies the gateway. You must use `elastic_path_payments_stripe` as the required gateway. | ### Request examples We recommend that you use the payment method or source with Stripe payments. For more information about generating a payment method on the client-side, see the [Stripe Elements](https://stripe.com/docs/payments/elements) documentation. :::caution When you pass `source` instead of a `token`, ensure that you include the Stripe customer ID in the request. ::: :::note If you are using Stripe API, pass your `Stripe-Account` ID in the header to make the payment. For example, see the following request: ```bash curl https://api.stripe.com/v1/payment_methods \ -u pk_live_EP_STRIPE_PUBLISHABLE_KEY: \ -H Stripe-Account:acct_xxxxxxx\ -d type=card \ -d "card[number]"=xxxxxxxxxxxx \ -d "card[exp_month]"=6 \ -d "card[exp_year]"=2023 \ -d "card[cvc]"=314 ``` ::: #### Curl ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/payments \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $ { "data": { "gateway": "elastic_path_payments_stripe", "method": "purchase", "amount": 5499, "payment": "pm_card_threeDSecureRequired", "options": { "receipt_email": "john@example.com" } } } ``` #### JavaScript SDK ```javascript const MoltinGateway = require("@moltin/sdk").gateway; const Moltin = MoltinGateway({ client_id: "X", }); const id = "XXXX"; const payment = { gateway: "elastic_path_payments_stripe", method: "purchase", payment: "pm_card_threeDSecureRequired", }; Moltin.Orders.Payment(id, payment).then(() => { // Do something }); ``` ### Response example `201 Created` :::note The `x` values in the `"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"` are replaced with the returned values. ::: ```json { "data": { "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "type": "transaction", "reference": "pi_xxxxxxxxxxxxx", "gateway": "elastic_path_payments_stripe", "amount": 5499, "currency": "USD", "transaction-type": "purchase", "transaction_type": "purchase", "status": "pending", "relationships": { "order": { "data": { "type": "order", "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } } }, "meta": { "display_price": { "amount": 5499, "currency": "USD", "formatted": "$54.99" }, "display_refunded_amount": { "total": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "created_at": "2019-08-28T10:40:21.925Z", "timestamps": { "created_at": "2019-08-28T10:40:21Z", "updated_at": "2019-08-28T10:40:23Z" } }, "client_parameters": { "token": "pi_xxxxxxxxxxxxxxxx", "secret": "pi_xxxxxxxxxxxxxx_secret_xxxxxxxxxxxxxx" } } } ``` ## Authorization or Purchase - `POST` Pay using Stripe Payment Element ```http https://useast.api.elasticpath.com/v2/orders/:orderId/payments ``` ### Parameters #### Path parameters | Name | Required | Type | Description | |:----------|:---------|:---------|:-------------------------------------------| | `orderId` | Required | `string` | The universally unique identifier of the order that you want to pay for. | #### Headers | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | #### Body :::note If both `payment_method_types` and ` automatic_payment_methods` are not enabled, the Stripe default, which is `card`, will be used. Attempting to set both `payment_method_types` and `automatic_payment_methods` to `true` will result in an error as Stripe doesn't allow both options to be enabled at the same time. ::: | Name | Required | Type | Description | |:------------------------|:---------|:---------|:-----------------------------| | `gateway` | Required | `string` | Specifies the gateway. You must use `elastic_path_payments_stripe` as the required gateway. | | `method` | Required | `string` | Specifies the transaction method, such as `purchase` or `authorize`. | | `options.receipt_email` | Optional | `string` | Provides the email address to which you want to send the Stripe receipts for the transactions within the store. This feature is available only in the live mode. | | `options.automatic_payment_methods.enabled` | Optional | `boolean` | When set to `true`, it displays all enabled payment methods from the [Stripe dashboard](https://dashboard.stripe.com/login). When set to `false`, the Stripe default, which is `card`, will be used. | | `payment_method_types` | Required | `string` | Specifies the Stripe payment method types configured for the store. See [Stripe Documentation](https://stripe.com/docs/api/payment_intents/create#create_payment_intent-payment_method_types). | ### Request examples #### Curl ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/payments \ -H "Authorization: Bearer XXXX" \ -d $ { "data": { "gateway": "elastic_path_payments_stripe", "method": "purchase", "options": { "receipt_email": "john@example.com" "automatic_payment_methods": { "enabled": true } } } } ``` #### JavaScript SDK ```javascript const MoltinGateway = require('@moltin/sdk').gateway const Moltin = MoltinGateway({ client_id: 'X' }) const id = 'XXXX' const payment = { gateway: 'elastic_path_payments_stripe', method: 'purchase', options: { receipt_email: "john@example.com" }, payment_method_types: ["link", "card"], } Moltin.Orders.Payment(id, payment).then(() => { // Do something }) ``` ### Response example `201 Created` ```json { "data": { "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "type": "transaction", "reference": "pi_xxxxxxxxxxxxxx", "gateway": "elastic_path_payments_stripe", "amount": 20000, "refunded_amount": 0, "currency": "USD", "transaction_type": "purchase-setup", "status": "pending", "relationships": { "order": { "data": { "type": "order", "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } } }, "meta": { "display_price": { "amount": 20000, "currency": "USD", "formatted": "$200.00" }, "display_refunded_amount": { "total": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2022-07-18T22:16:11Z", "updated_at": "2022-07-18T22:16:32Z" } }, "client_parameters": { "token": "pi_xxxxxxxxxxxxxx", "secret": "pi_xxxxxxxxxxxxxx_secret_xxxxxxxxxxxxxx" }, "payment_intent": { "amount": 20000, "amount_capturable": 0, "amount_details": { "tip": {} }, "amount_received": 0, "application": { "deleted": false, "id": "ca_KH5gI4U1QcTNYo08rUpmVAGds0YBp0ZG", "name": "", "object": "" }, "application_fee_amount": null, "automatic_payment_methods": { "enabled": true }, "canceled_at": null, "cancellation_reason": null, "capture_method": "manual", "charges": { "data": [], "has_more": false, "object": "list", "total_count": 0, "url": "/v1/charges?payment_intent=pi_xxxxxxxxxxxxxx" }, "client_secret": "pi_xxxxxxxxxxxxxx_secret_xxxxxxxxxxxxxx", "confirmation_method": "automatic", "created": 1658182571, "currency": "usd", "customer": null, "description": null, "id": "pi_xxxxxxxxxxxxxx", "invoice": null, "last_payment_error": null, "livemode": false, "metadata": { "email": "andy@example.com", "ip_address": "##.###.###.###", "order_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }, "next_action": null, "object": "payment_intent", "on_behalf_of": null, "payment_method": null, "payment_method_options": { "acss_debit": null, "affirm": null, "afterpay_clearpay": null, "alipay": null, "au_becs_debit": null, "bacs_debit": null, "bancontact": { "preferred_language": "en", "setup_future_usage": "" }, "blik": null, "boleto": null, "card": { "capture_method": "", "installments": null, "mandate_options": null, "network": "", "request_three_d_secure": "automatic", "setup_future_usage": "", "statement_descriptor_suffix_kana": "", "statement_descriptor_suffix_kanji": "" }, "card_present": null, "customer_balance": null, "eps": { "setup_future_usage": "" }, "fpx": null, "giropay": { "setup_future_usage": "" }, "grabpay": null, "ideal": { "setup_future_usage": "" }, "interac_present": null, "klarna": null, "konbini": null, "link": { "capture_method": "", "persistent_token": "", "setup_future_usage": "" }, "oxxo": null, "p24": { "setup_future_usage": "" }, "paynow": null, "promptpay": null, "sepa_debit": { "mandate_options": null, "setup_future_usage": "" }, "sofort": null, "us_bank_account": null, "wechat_pay": null }, "payment_method_types": [ "card", "bancontact", "eps", "giropay", "ideal", "p24", "sepa_debit", "link" ], "processing": null, "receipt_email": "john@example.com", "review": null, "setup_future_usage": "", "shipping": null, "source": null, "statement_descriptor": "", "statement_descriptor_suffix": "", "status": "requires_payment_method", "transfer_data": null, "transfer_group": "" }, "payment_details": { "detailed_status": "requires_payment_method" }, "next_actions": [ "cancel" ] } } ``` ## Authorization or Purchase - `POST` Pay using 3D Secure ```http https://useast.api.elasticpath.com/v2/orders/:orderId/payments ``` ### Parameters #### Path parameters | Name | Required | Type | Description | |:----------|:---------|:---------|:-------------------------------------------| | `orderId` | Required | `string` | The universally unique identifier of the order that you want to pay for. | #### Headers | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | #### Body | Name | Required | Type | Description | |:------------------------|:---------|:---------|:-----------------------------| | `gateway` | Required | `string` | Specifies the gateway. You must use `elastic_path_payments_stripe` as the required gateway. | | `method` | Required | `string` | Specifies the transaction method, such as `purchase` or `authorize`. | | `payment` | Required | `string` | Use `pm_card_threeDSecureRequired` or `pm_card_threeDSecure2Required`. | | `options.return_url` | Optional | `string` | Indicates the URL to redirect the user in the case of approved payment.| | `options.receipt_email` | Optional | `string` | Provides the email address to which you want to send the Stripe receipts for the transactions within the store. This feature is available only in the live mode. | | `options.confirm` | Optional | `boolean` | Set to `true` to confirm the payment. Default value is `true`. | | `options.execute_threed` | Optional | `boolean` | Set this field to `true` to use 3D secure. Default value is `true`. | | `confirmation_method` | Required | `string` | Specifies confirmation method for payment. Values can be set to `manual` or `automatic`. Default is `automatic`. | ### Request Example - Curl ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/payments \ -H "Authorization: Bearer XXXX" \ -d $'{ "data": { "gateway": "elastic_path_payments_stripe", "method": "authorize", "payment": "pm_card_threeDSecureRequired", "options": { "return_url": "https://your.frontend.url/return", "receipt_email": "john@example.com", "confirm": true, "execute_threed": true, "confirmation_method": "manual" } } } ``` ### Response Example `200 OK` ```Json { "data": { "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "type": "transaction", "reference": "pi_xxxxxxxxxxxxxx", "gateway": "elastic_path_payments_stripe", "amount": 20000, "refunded_amount": 0, "currency": "USD", "transaction_type": "authorize", "status": "pending", "relationships": { "order": { "data": { "type": "order", "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } } }, "meta": { "display_price": { "amount": 20000, "currency": "USD", "formatted": "$200.00" }, "display_refunded_amount": { "total": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2023-03-09T14:01:32Z", "updated_at": "2023-03-09T14:01:33Z" } }, "client_parameters": { "token": "pi_xxxxxxxxxxxxxx", "secret": "pi_xxxxxxxxxxxxxx_secret_xxxxxxxxxxxxxx" }, "payment_intent": { "amount": 20000, "amount_capturable": 0, "amount_details": { "tip": {} }, "amount_received": 0, "application": "ca_xxxxxxxxxxxxxx", "application_fee_amount": null, "automatic_payment_methods": null, "canceled_at": null, "cancellation_reason": null, "capture_method": "manual", "charges": { "data": [], "has_more": false, "object": "list", "total_count": 0, "url": "/v1/charges?payment_intent=pi_xxxxxxxxxxxxxx" }, "client_secret": "pi_xxxxxxxxxxxxxx_secret_xxxxxxxxxxxxxx", "confirmation_method": "manual", "created": 1678370492, "currency": "usd", "customer": null, "description": null, "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "invoice": null, "last_payment_error": null, "latest_charge": null, "livemode": false, "metadata": { "email": "andy@example.com", "ip_address": "174.91.171.193", "order_id": "73f1bd38-8dda-441a-98b3-57d05af4d9ac" }, "next_action": { "redirect_to_url": { "return_url": "https://your.frontend.url/return", "url": "https://hooks.stripe.com/redirect/authenticate/src_1Mjk2CS5G6YfGRXYqAAR6EsF?client_secret=src_client_secret_XEsFaMSCQwEeDnVUbQUa9P8P&source_redirect_slug=test_YWNjdF8xS2pBaElTNUc2WWZHUlhZLF9OVWpWT2N0eDJoNGRjQkhJMnhsUkUyNmdpd2NkM0xk01003bGfQmde" }, "type": "redirect_to_url" }, "object": "payment_intent", "on_behalf_of": null, "payment_method": "pm_xxxxxxxxxxxx", "payment_method_options": { "card": { "installments": null, "mandate_options": null, "network": null, "request_three_d_secure": "automatic" } }, "payment_method_types": [ "card" ], "processing": null, "receipt_email": "john@example.com", "review": null, "setup_future_usage": null, "shipping": null, "source": null, "statement_descriptor": null, "statement_descriptor_suffix": null, "status": "requires_action", "transfer_data": null, "transfer_group": null }, "payment_details": { "detailed_status": "requires_action" }, "next_actions": [ "cancel" ] } } ``` ## Confirmation - `POST` Confirm the Security Validation ```http https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/confirm ``` ### Parameters #### Path parameters | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `orderId` | Required | `string` | The universally unique identifier of the order that you want to pay for. | | `transactionId` | Required | `string` | The universally unique identifier of the transaction that requires client action to process validation. | #### Headers | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | ### Request example If the response for the authorization or purchase request consists of `client_parameters`, Stripe might required client action to perform a 3D Secure validation. Use the Stripe client libraries and process the 3D Secure validation. When the validation succeeds, continue the payment processing by making a request as in the following example: ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/confirm \ -H "Authorization: Bearer XXXX" \ -d $ { "data": { } } ``` ### Response example `201 Created` :::note The `x` values in the `"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"` are replaced with the returned values. ::: ```json { "data": { "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "type": "transaction", "reference": "xxxxxx", "gateway": "elastic_path_payments_stripe", "amount": 100, "currency": "USD", "transaction_type": "purchase", "status": "complete", "relationships": { "order": { "data": { "type": "order", "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } } }, "meta": { "display_price": { "amount": 100, "currency": "USD", "formatted": "$100.00" }, "display_refunded_amount": { "total": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2020-05-25T20:58:57Z", "updated_at": "2020-05-25T13:59:01-07:00" } } } } ``` ## Confirmation - `POST` Capture the Payment Authorization ```http https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/capture ``` Use this endpoint to capture a transaction initiated by the shopper. Usually capture does not occur at the same time as authorization. For more information, see the [Capture](/docs/api/carts/payments#capture) section. ### Parameters #### Path parameters | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `orderId` | Required | `string` | The universally unique identifier of the order that you want to pay for. | | `transactionId` | Required | `string` | The universally unique identifier of the successful transaction for this payment. | #### Headers | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | ### Request example ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/capture \ -H "Authorization: Bearer XXXX" ``` ### Response example `201 Created` :::note The `x` values in the `"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"` are replaced with the returned values. ::: ```json { "data": { "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "type": "transaction", "reference": "xxxxxx", "gateway": "elastic_path_payments_stripe", "amount": 100, "currency": "USD", "transaction_type": "capture", "status": "complete", "relationships": { "order": { "data": { "type": "order", "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } } }, "meta": { "display_price": { "amount": 100, "currency": "USD", "formatted": "$100.00" }, "display_refunded_amount": { "total": { "amount": 0, "currency": "USD", "formatted": "$0.00" } }, "timestamps": { "created_at": "2020-05-25T20:58:57Z", "updated_at": "2020-05-25T13:59:01-07:00" } } } } ``` ## Refund - `Post` Refund the Payment ```http https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/refund ``` Use this endpoint to refund the amount initiated by the shopper. ### Parameters #### Path parameters | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `orderId` | Required | `string` | The universally unique identifier of the order that you want to pay for. | | `transactionId` | Required | `string` | The universally unique identifier of the successful transaction for this payment. | #### Headers | Name | Required | Type | Description | |:----------------|:---------|:---------|:-------------------------------------| | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | #### Body | Name | Required | Type | Description | |:------------------------|:---------|:----------|:----------------------------| | `amount` | Required | `integer` | Specifies the amount to be refunded. | | `options.note_to_payer` | Optional | `string` | Specifies the reason for the refund. It appears in both the transaction history of the payer and the emails that the payer receives. | ### Request example ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/refund \ -H "Authorization: Bearer XXXX" "data": { "amount": 1, "options": { "note_to_payer": "Test note to payer" } } } ``` ### Response example `200 OK` ```json { "data": { "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "type": "transaction", "reference": "pi_3Kr4EBHGgiZNYgWz1eio9cFS", "gateway": "elastic_path_payments_stripe", "amount": 80000, "refunded_amount": 2, "refund_mechanism": "automatic", "currency": "GBP", "transaction_type": "refund", "status": "complete", "relationships": { "order": { "data": { "type": "order", "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } } }, "meta": { "display_price": { "amount": 80000, "currency": "GBP", "formatted": "£800.00" }, "display_refunded_amount": { "total": { "amount": 2, "currency": "GBP", "formatted": "£0.02" } }, "timestamps": { "created_at": "2022-04-21T17:55:38Z", "updated_at": "2022-04-22T15:37:07Z" } } } } ``` --- ## Refund a Payment import Video from "/src/components/CardDisplay/video"; There are two ways to refund; through your payment gateway and mark it refunded in Commerce Manager, or directly through Commerce Manager or API. - **Mark as Refunded**: You can manually mark a transaction as refunded. Before you can mark the order as refunded, you need to handle the actual refund on your side with your payment provider. **Mark as Refunded** is a full refund made to the transaction. - **Refund** through Composable Commerce: You can process a full or partial refund to a supported payment provider directly from Commerce Manager or API by providing the refund amount. When you start the refund process, the request is directly sent to the payment gateway. :::caution If you use manual gateway for partial or full refund, you need to handle the actual refund on your side with your payment provider. ::: With split payments, you can initiate a refund for a specific transaction. You can only initiate a refund against a transaction if the order status is `complete` and payment status is `paid`, or the order is `cancelled`. - Ensure that the transaction is already captured and complete to refund a specific transaction. The maximum refund amount is equal to the transaction amount. You can issue the refund to the original payment method of the transaction. - Each transaction must be refunded independently to fully refund an order with multiple transactions. - Refund amount cannot exceed the total transaction amount and the order amount. - You can initiate multiple partial refunds for a single transaction. For example, the total order amount is $100 with two transactions, where the first transaction value is $60 and the second is $40. In this case, you can initiate multiple partial refunds for the first transaction until the total refunded amount is equal to $60. Similarly, you can initiate multiple partial refunds for the second transaction until the total refunded amount is $40. ## `POST` Refund a Full Payment ```http https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/refund ``` ### Parameters #### Path parameters | Name | Required | Type | Description | | --- | --- | --- | --- | | `transactionId` | Required | `string` | The UUID of the transaction you want to refund. | | `orderId` | Required | `string` | The UUID of the order. | #### Headers | Name | Required | Type | Description | | --- | --- | --- | --- | | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | #### Body | Name | Required | Type | Description | |----------|----------|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `amount` | Optional | `integer` | The amount value to be refunded. If this field is not provided, it will be considered as manual refund (Mark as Refunded) and the refund process must be manually handled via payment provider. If the amount value is same as payment value, then it will be treated as a full refund and sent to the payment provider to process refund automatically. | ### Request Example - Mark as Refunded (manual) When you manually mark as refunded, you do not need to provide any request body. ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/refund \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ ``` ### Request Example - Full Refund (automatic) When you want to full refund the payment via payment provider automatically, you need to provide the amount value in request body. ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/refund \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $'{ "data": { "amount": , } }' ``` #### Optional parameters :::note Ensure that you use the correct `option` parameter for your payment provider. For example, PayPal Express uses the `note` parameter where you can provide comments about the refund. ::: ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/refund \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $'{ "data": { "amount": , "options": { "note": "PayPal Express users" } }' ``` ### Response example `200 OK` ```json { "data": { "id": "6112f8b0-ce4e-4ef8-a117-cb741654efa5", "type": "transaction", "reference": "B8PP0D6ABE57", "gateway": "", "amount": 10000, "refunded_amount": 10000, "refund_mechanism": "automatic", "currency": "USD", "transaction_type": "refund", "status": "complete", "relationships": { "order": { "data": { "type": "order", "id": "1b031452-b048-43b9-a06c-feafe6e4bc31" } }, "timestamps": { "created_at": "2020-07-03T21:07:45Z", "updated_at": "2020-07-03T14:09:12-07:00" } }, "meta": { "display_price": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "display_refunded_amount": { "total": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } }, "timestamps": { "created_at": "2020-07-03T21:10:14Z", "updated_at": "2020-07-03T14:11:59-07:00" } }, "meta": { "display_price": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "display_refunded_amount": { "total": { "amount": 10000, "currency": "USD", "formatted": "$100.00" } }, "timestamps": { "created_at": "2020-07-03T21:10:14Z", "updated_at": "2020-07-03T14:11:59-07:00" } } } } ``` ## `POST` Refund a Partial Payment ```http https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/refund ``` ### Parameters #### Path parameters | Name | Required | Type | Description | | --- | --- | --- | --- | | `transactionId` | Required | `string` | The UUID of the transaction you want to refund. | | `orderId` | Required | `string` | The UUID of the order. | #### Headers | Name | Required | Type | Description | | --- | --- | --- | --- | | `Authorization` | Required | `string` | The Bearer token required to get access to the API. | #### Body | Name | Required | Type | Description | |----------|----------|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `amount` | Required | `integer` | The amount value to be refunded. Partial refund requires the amount value to be specified. The request will be sent to the payment provider and processed automatically. | ### Request example - Curl :::note Ensure that you list the amount of the refund in cents. For example, for a refund of $10.00, put `1000`. Also ensure that you use the correct `option` parameter for your payment provider. For example, PayPal Express uses the `note` parameter where you can provide comments about the refund. ::: ```bash curl -X POST https://useast.api.elasticpath.com/v2/orders/:orderId/transactions/:transactionId/refund \ -H "Authorization: Bearer XXXX" \ -H "Content-Type: application/json" \ -d $' { "data": { "amount": 5000, "options": { "note": "PayPal Express users" } }' ``` ### Response example `200 OK` ```json { "data": { "id": "d1e0b7db-3112-47ee-aaf9-c96d6a94bbcc", "type": "transaction", "reference": "B8PP0D6494BD", "gateway": "", "amount": 10000, "refunded_amount": 5000, "refund_mechanism": "automatic", "currency": "USD", "transaction_type": "refund", "status": "complete", "relationships": { "order": { "data": { "type": "order", "id": "09a46cb9-4eb7-49c9-97f1-e0c8085017a6" } } }, "meta": { "display_price": { "amount": 10000, "currency": "USD", "formatted": "$100.00" }, "display_refunded_amount": { "total": { "amount": 5000, "currency": "USD", "formatted": "$50.00" } }, "timestamps": { "created_at": "2020-06-26T23:06:02Z", "updated_at": "2020-06-26T23:06:50Z" } } } } ``` ## Demos