Extending the Magento web services API
08 Mar 2010, by Peter Spiller
4 Comments · Posted in Magento

    First of all, you need to find the Magento core file that provides the API method you want to extend. These are generally in model files called Api.php or under directories called Api. For example, I recently needed to look up customer orders by their IDs, as opposed to their increment IDs (aka their order numbers, such as '#100000003'). After some searching, I found the file that contains the relevant code at app/code/core/Mage/Sales/Model/Order/Api.php, in the _initOrder() method:

    
        protected function _initOrder($orderIncrementId)
        {
            $order = Mage::getModel('sales/order');
    
            /* @var $order Mage_Sales_Model_Order */
    
            $order->loadByIncrementId($orderIncrementId);
    
            if (!$order->getId()) {
                $this->_fault('not_exists');
            }
    
            return $order;
        }
    

    To override this, we could put a copy of the file in app/code/local, but that would mean copying the whole file and effectively overriding all the methods in it. Unfortunately this approach can be problematic when upgrading, since other modules may depend on new methods in the API model that aren't available due to the override. A better approach would be to only modify the function we are interested in. Create a file called Example_Webservices.xml in app/etc/modules, containing:

    <?xml version="1.0"?>
    <config>
        <modules>
            <Example_Webservices>
                <active>true</active>
                <codePool>local</codePool>
            </Example_Webservices>
        </modules>
    </config>
    

    Create the directory app/code/local/Example/Webservices/etc, and create a file called config.xml containing:

    <?xml version="1.0"?>
    <config>
        <global>
            <models>
                <sales>
                    <rewrite>
                        <order_api>Example_Webservices_Model_Sales_Order_Api</order_api>
                    </rewrite>
                </sales>
            </models>
        </global>
    </config>
    

    This is the usual code for overriding a model. We're rewriting all requests for the Mage_Sales_Model_Order_Api class to our own Example_Webservices_Model_Sales_Order_Api class.

    Finally, we need to actually create our model and override the method we're interested in. Create app/code/local/Example/Webservices/Model/Sales/Order/Api.php containing:

    
    class Example_Webservices_Model_Sales_Order_Api extends Mage_Sales_Model_Order_Api
    {
        protected function _initOrder($orderIncrementId)
        {
            $order = Mage::getModel('sales/order');
    
            if(is_string($orderIncrementId)) {
                $order->loadByIncrementId($orderIncrementId);
                if (!$order->getId()) {
                    $this->_fault('not_exists');
                }
            } else {
                $order->load($orderIncrementId);
                if (!$order->getId()) {
                    $this->_fault('not_exists');
                }
            }
            return $order;
        }
    }
    

    This class overrides the original model class we're overriding - this way, we only change the specific methods we want to change and minimise the chance of interfering with an upgrade. The modifications to the body of the method are quite simple. Instead of always loading by increment ID, we first check if the $orderIncrementId parameter we are passed is a string. If it's a string, we do an increment ID lookup; if not, we assume it's an ID and look up on that. This works in a similar way to products, where you can use the API to get a product by either ID or SKU.

    If your Magento store needs to work with another application in a way that Magento doesn't support, this simple example shows how easy it is to extend Magento's web services API's to allow you to achieve the integration that you require.