Extending the Magento web services API

Magento provides a handy web services API for integration with other software systems, and it can be extended if you need it to do something that it doesn't do by default. However, incorrectly overriding core Magento code can cause incompatibilities when applying upgrades. The following is an example of how to extend the API in a way that attempts to avoid introducing problems with future releases.

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.

api

Comments

excellent post!! really helpful. better approach would be to only modify the function we are interested in

If you want to add method to API you have to define it in api.xml file. For example:

<config>
    <api>
        <resources>
            <sales_order translate="title" module="sales">
                <model>sales/order_api</model>
                <title>Order API</title>
                <acl>sales/order</acl>
                <methods>
                    ...
                    <create translate="title" module="sales">
                        <title>Create order</title>
                        <acl>sales/order/create</acl>
                    </create>                 
                </methods>
            </sales_order>
            ...
         </resources>
        ...
       </api>
</config>

Hi! This seems exactly what i have been looking for... But how can you call it? Can you call it like methods inside magento web service api? I mean would something like this work outside magento:

$mag_connection = new SoapClient( 'http://server/magento/api/soap/?wsdl' );
$mag_session = $mag_connection->login( 'apiU', 'apiK' );
$list = $mag_connection->call($mag_session, 'order.initOrder.);
var_dump($list);

Peter, this is a great tutorial - in fact, all the Fontis tutorials are great ;)

This approach works great when you're extending an existing API - but let's say that we want to create an API from scratch ...

In our case we're building a custom extension to handle task management for different users inside Magento's Admin. We have API integration (sales orders, invoices, shipments) within our accounting system (Microsoft Dynamics NAV) already but we want to create a button in NAV to notify someone in Magento that there is a problem with an order by creating a task through a new API to our custom extension.

I can't find documentation on creating a new API for our tasks extension - only on how to extend existing APIs. Can you give me any direction?

Darren.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <apache>, <bash>, <c>, <cpp>, <drupal5>, <drupal6>, <java>, <javascript>, <perl>, <php>, <python>, <ruby>, <xml>. The supported tag styles are: <foo>, [foo].

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.