Magento 2 Catalog Price Rule is not exposed as a REST API End Point. Catalog Price Rule API feature is an important feature for those who work in Creating Mobile App and Third Party Integration. Though this feature is not available we can extend magento core with our custom code to expose this API End Point
Lets see how to achieve this with our custom code.
Step 1 : Create and enable our new custom module
app/code/Mydons/CatalogRuleApi/registration.php
1 2 3 4 5 6 |
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Mydons_CatalogRuleApi', __DIR__ ); |
app/code/Mydons/CatalogRuleApi/etc/module.xml
1 2 3 4 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Mydons_CatalogRuleApi" setup_version="1.0.0"/> </config> |
Step 2:- Once after creating the module.xml and registration.php we need to create an webapi.xml file to define the REST API End Points.
The Core Magento 2 CatalogRule module already contains the necessary code for carrying out the API Operation in the below files, only drawback is those methods were not exposed as webapi end points. Lets define the REST API route path as “catalogRules”.
Though the main methods are all available in magento core, the “getList” method is not available by default and we will implement it separately. For this demo i am skipping the ACL Part and defining the “resource ref” as anonymous
Magento 2 Core Files Reference:-
Magento\CatalogRule\Api\interface\CatalogRuleRepositoryInterface
Magento\CatalogRule\Model\Rule.php
File:- app/code/Mydons/CatalogRuleApi/etc/webapi.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?xml version="1.0"?> <routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd"> <route url="/V1/catalogRules/:ruleId" method="GET"> <service class="Magento\CatalogRule\Api\CatalogRuleRepositoryInterface" method="get"/> <resources> <resource ref="anonymous" /> </resources> </route> <route url="/V1/catalogRules/search" method="GET"> <service class="Mydons\CatalogRuleApi\Api\CatalogRuleRepositoryInterface" method="getList"/> <resources> <resource ref="anonymous" /> </resources> </route> <route url="/V1/catalogRules/:ruleId" method="DELETE"> <service class="Magento\CatalogRule\Api\CatalogRuleRepositoryInterface" method="deleteById"/> <resources> <resource ref="anonymous" /> </resources> </route> <route url="/V1/catalogRules/:ruleId" method="PUT"> <service class="Magento\CatalogRule\Api\CatalogRuleRepositoryInterface" method="save"/> <resources> <resource ref="anonymous" /> </resources> </route> <route url="/V1/catalogRules" method="POST"> <service class="Magento\CatalogRule\Api\CatalogRuleRepositoryInterface" method="save"/> <resources> <resource ref="anonymous" /> </resources> </route> </routes> |
Step 3:- In the above webapi.xml for getting the list of all catalogRules we need to implement our custom “getList” method in
File:- Mydons\CatalogRuleApi\Api\CatalogRuleRepositoryInterface
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php namespace Mydons\CatalogRuleApi\Api; use \Magento\Framework\Api\SearchCriteriaInterface; interface CatalogRuleRepositoryInterface { /** * Get rules * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria * @return \Magento\Framework\Api\SearchResultsInterface */ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria); } |
Step 4:- We need to create the di.xml to specify the preference implementation classes for both our custom interface and core module interface.
File: app/code/Mydons/CatalogRuleApi/etc/di.xml
1 2 3 4 5 6 7 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Mydons\CatalogRuleApi\Api\CatalogRuleRepositoryInterface" type="Mydons\CatalogRuleApi\Model\CatalogRuleManagement" /> <preference for="Magento\CatalogRule\Api\CatalogRuleRepositoryInterface" type="Magento\CatalogRule\Model\CatalogRuleRepository" /> </config> |
Step 5:- At this point now we can execute the below REST API methods V1/catalogRules/:ruleId GET, DELETE, POST, PUT. But the problem here is the GET Method returns data without website_ids and customer_group_ids as show in the below screenshot.

To resolve this problem we can add the website_ids and customer_group_ids in extension_attributes.xml file and hook the GET Method Using Plugin to add the missing data.
File: app/code/Mydons/CatalogRuleApi/etc/extension_attributes.xml
1 2 3 4 5 6 7 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\CatalogRule\Api\Data\RuleInterface"> <attribute code="website_ids" type="int[]"/> <attribute code="customer_group_ids" type="int[]"/> </extension_attributes> </config> |
File: app/code/Mydons/CatalogRuleApi/Data/RuleExtensionInterface.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?php namespace Mydons\CatalogRuleApi\Api\Data; interface RuleExtensionInterface { /** * * @return \Magento\CatalogRule\Api\Data\RuleExtensionInterface */ public function getWebsiteIds(); /** * @param \Magento\CatalogRule\Api\Data\RuleExtensionInterface[] * @return $this */ public function setWebsiteIds(); /** * * @return \Magento\CatalogRule\Api\Data\RuleExtensionInterface */ public function getCustomerGroupIds(); /** * @param \Magento\CatalogRule\Api\Data\RuleExtensionInterface[] * @return $this */ public function setCustomerGroupIds(); } |
Now we need to add the plugin specification in the existing di.xml file to retrieve and save the website_ids and customer_group_ids properly
File: app/code/Mydons/CatalogRuleApi/etc/di.xml
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Mydons\CatalogRuleApi\Api\CatalogRuleRepositoryInterface" type="Mydons\CatalogRuleApi\Model\CatalogRuleManagement" /> <preference for="Magento\CatalogRule\Api\CatalogRuleRepositoryInterface" type="Magento\CatalogRule\Model\CatalogRuleRepository" /> <!-- Plugin to Hook the Get Method --> <type name="Magento\CatalogRule\Api\CatalogRuleRepositoryInterface"> <plugin name="mydons_add_websitecustomerids_extension_attribute" type="Mydons\CatalogRuleApi\Plugin\CatalogRuleRepositoryPlugin" /> </type> </config> |
File: app/code/Mydons/CatalogRuleApi/Plugin/CatalogRuleRepositoryPlugin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
<?php namespace Mydons\CatalogRuleApi\Plugin; use Magento\CatalogRule\Api\Data\RuleExtensionFactory; use Magento\CatalogRule\Api\Data\RuleExtensionInterface; use Magento\CatalogRule\Api\Data\RuleInterface; use Magento\CatalogRule\Api\CatalogRuleRepositoryInterface; /** * Class CatalogRuleRepositoryPlugin */ class CatalogRuleRepositoryPlugin { /** * Rule Extension Attributes Factory * * @var RuleExtensionFactory */ protected $extensionFactory; /** * CatalogRuleRepositoryPlugin constructor * * @param RuleExtensionFactory $extensionFactory */ public function __construct(RuleExtensionFactory $extensionFactory) { $this->extensionFactory = $extensionFactory; } /** * Add "customer_group_ids" and "website_ids" extension attributes to catalog rule object to make it accessible in API data * * @param CatalogRuleRepositoryInterface $subject * @param RuleInterface $rule * * @return RuleInterface */ public function afterGet(CatalogRuleRepositoryInterface $subject, RuleInterface $rule) { $websiteIds = $rule->getData('website_ids'); $customerGroupIds = $rule->getCustomerGroupIds(); $extensionAttributes = $rule->getExtensionAttributes(); $extensionAttributes = $extensionAttributes ? $extensionAttributes : $this->extensionFactory->create(); $extensionAttributes->setWebsiteIds($websiteIds); $extensionAttributes->setCustomerGroupIds($customerGroupIds); $rule->setExtensionAttributes($extensionAttributes); return $rule; } /** * Add "customer_group_ids" and "website_ids" extension attributes to catalog rule object to make it accessible in API data * * @param CatalogRuleRepositoryInterface $subject * @param RuleInterface $rule * * @return array */ public function beforeSave(CatalogRuleRepositoryInterface $subject, RuleInterface $rule) { $extensionAttributes = $rule->getExtensionAttributes() ?: $this->extensionFactory->create(); if ($extensionAttributes !== null && $extensionAttributes->getWebsiteIds() !== null) { $rule->setWebsiteIds($extensionAttributes->getWebsiteIds()); } if ($extensionAttributes !== null && $extensionAttributes->getCustomerGroupIds() !== null) { $rule->setCustomerGroupIds($extensionAttributes->getCustomerGroupIds()); } return [$rule]; } } |

Step 6: Now we need to add our custom getList Method implementation to Fetch all the Catalog Price Rules.
File: app/code/Mydons/CatalogRuleApi/Model/CatalogRuleManagement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
<?php namespace Mydons\CatalogRuleApi\Model; use \Magento\CatalogRule\Model\RuleFactory; class CatalogRuleManagement implements \Mydons\CatalogRuleApi\Api\CatalogRuleRepositoryInterface { /** * @var RuleFactory */ protected $_catalogRuleFactory; /** * @var \Magento\Framework\Api\SearchResultsInterface */ protected $searchResultsFactory; /** * @var array */ private $rules = []; /** * @param RuleFactory $catalogRuleFactory * @param \Magento\Framework\Api\SearchResultsInterface $searchResultsFactory * @param DataObjectHelper $dataObjectHelper * @param DataObjectProcessor $dataObjectProcessor */ public function __construct( RuleFactory $catalogRuleFactory, \Magento\Framework\Api\SearchResultsInterface $searchResultsFactory, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor ) { $this->_catalogRuleFactory = $catalogRuleFactory; $this->searchResultsFactory = $searchResultsFactory; $this->dataObjectHelper = $dataObjectHelper; $this->dataObjectProcessor = $dataObjectProcessor; } /** * @api * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria * @return \Magento\Framework\Api\SearchResultsInterface */ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria) { $searchResults = $this->searchResultsFactory; //->create(); $searchResults->setSearchCriteria($searchCriteria); $catalogRule = $this->_catalogRuleFactory->create(); $catalogRuleCollection = $catalogRule->getCollection(); foreach ($searchCriteria->getFilterGroups() as $filterGroup) { $fields = []; $conditions = []; foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $fields[] = $filter->getField(); $conditions[] = [$condition => $filter->getValue()]; } if ($fields) { $catalogRuleCollection->addFieldToFilter($fields, $conditions); } } $searchResults->setTotalCount($catalogRuleCollection->getSize()); $catalogRuleCollection->setCurPage($searchCriteria->getCurrentPage()); $catalogRuleCollection->setPageSize($searchCriteria->getPageSize()); foreach($catalogRuleCollection as $ruleModel) { $catalogRuleData = $this->_catalogRuleFactory->create(); $this->rules[] = $ruleModel->getData(); } $this->searchResultsFactory->setItems($this->rules); return $this->searchResultsFactory; } } |
Now We can try hitting the postman with searchCriteria as shown below
rest/V1/catalogRules/search?searchCriteria[filter_groups][0][filters][0][field]=rule_id&searchCriteria[filter_groups][0][filters][0][value]=1&searchCriteria[filter_groups][0][filters][0][condition_type]=eq&searchCriteria[pageSize]=10

Sample Request Response Format
Method:- PUT
URL:- rest/V1/catalogRules/:ruleId
Sample Request Format:-
(Pass only the parameters which needs to be modified)
{
“rule”: {
“name”: “15% off all Women’s and Men’s Pants”,
“description”: “15% off all Women’s and Men’s Pants”,
“is_active”: 1,
“rule_condition”: {
“type”: “Magento\CatalogRule\Model\Rule\Condition\Combine”,
“attribute”: “”,
“operator”: “”,
“value”: “1”,
“is_value_parsed”: false,
“aggregator”: “all”,
“conditions”: [
{
“type”: “Magento\CatalogRule\Model\Rule\Condition\Product”,
“attribute”: “category_ids”,
“operator”: “()”,
“value”: “27”,
“is_value_parsed”: false,
“aggregator”: “”
}
]
},
“stop_rules_processing”: 1,
“sort_order”: 0,
“simple_action”: “by_percent”,
“discount_amount”: 15,
“extension_attributes”: {
“website_ids”: [
“1”
],
“customer_group_ids”: [
“0”,
“2”
]
}
}
}
Method:- POST
URL:- rest/V1/catalogRules/:ruleId
Sample Request Format:-
(Pass only the parameters which needs to be modified)
{
“rule”: {
“name”: “15% off all Women’s and Men’s Pants”,
“description”: “15% off all Women’s and Men’s Pants”,
“is_active”: 1,
“rule_condition”: {
“type”: “Magento\CatalogRule\Model\Rule\Condition\Combine”,
“attribute”: “”,
“operator”: “”,
“value”: “1”,
“is_value_parsed”: false,
“aggregator”: “all”,
“conditions”: [
{
“type”: “Magento\CatalogRule\Model\Rule\Condition\Product”,
“attribute”: “category_ids”,
“operator”: “()”,
“value”: “27”,
“is_value_parsed”: false,
“aggregator”: “”
}
]
},
“stop_rules_processing”: 1,
“sort_order”: 0,
“simple_action”: “by_percent”,
“discount_amount”: 15,
“extension_attributes”: {
“website_ids”: [
“1”
],
“customer_group_ids”: [
“0”,
“2”
]
}
}
}
I am Working on the ACL part of the above module, if anyone is interested in the above module drop your email in the comment, i’ll provide the source code.