Magento – How to Create Custom SOAP/XML-RPC API

apimagento-1.6php-5.4

How can I create a Custom SOAP/XML-RPC V1 & V2 API in Magento?

Best Answer

You can read this. It explains a lot but it's mostly for API V1.
To show you how you can create an API I think it's better to offer an example.
Let's say you have a module named Easylife_Portfolio with an entity named Project.
For this entity you can set the name, description and status.
Here are the files you need in addition to the rest of the files (controllers, models, blocks..).
app/code/local/Easylife/Portfolio/etc/api.xml - the api declaration file.

<?xml version="1.0"?>
<config>
    <api>
        <resources>
            <portfolio_project translate="title" module="portfolio">
                <title>Project API</title>
                <model>portfolio/project_api</model>
                <acl>portfolio/project</acl><!-- acl resource alias -->
                <methods><!-- definne the methods -->
                    <list translate="title" module="portfolio"><!-- list projects -->
                        <title>Retrieve list of projects</title>
                        <method>items</method>
                        <acl>portfolio/project/list</acl>
                    </list>
                    <info translate="title" module="portfolio"><!-- project details -->
                        <title>Retrieve project info</title>
                        <acl>portfolio/project/info</acl>
                    </info>
                    <add translate="title" module="portfolio"><!-- add project -->
                        <title>Add project</title>
                        <acl>portfolio/project/add</acl>
                    </add>
                    <update translate="title" module="portfolio"><!-- update project -->
                        <title>Update project</title>
                        <acl>portfolio/project/update</acl>
                    </update>
                    <remove translate="title" module="portfolio"><!-- remove project-->
                        <title>Remove project</title>
                        <acl>portfolio/project/remove</acl>
                    </remove>
                </methods>
                <faults module="portfolio"><!-- errors that might appear-->
                    <project_not_exists>
                        <code>101</code>
                        <message>Requested project does not exist.</message>
                    </project_not_exists>
                    <invalid_data>
                        <code>102</code>
                        <message>Provided data is invalid.</message>
                    </invalid_data>
                    <save_error>
                        <code>103</code>
                        <message>Error while saving project. Details in error message.</message>
                    </save_error>
                    <remove_error>
                        <code>104</code>
                        <message>Error while removing project. Details in error message.</message>
                    </remove_error>
                </faults>
            </portfolio_project>
        </resources>
        <resources_alias>
            <project>portfolio_project</project>
        </resources_alias>
        <v2>
            <resources_function_prefix>
                <project>portfolioProject</project>
            </resources_function_prefix>
        </v2>
        <acl><!-- acl definition -->
            <resources>
                <portfolio translate="title" module="portfolio">
                    <title>Portfolio</title>
                    <project translate="title" module="portfolio">
                        <title>Project</title>
                        <sort_order>110</sort_order>
                        <list translate="title" module="portfolio">
                            <title>List</title>
                        </list>
                        <info translate="title" module="portfolio">
                            <title>Info</title>
                        </info>
                        <add translate="title" module="portfolio">
                            <title>Add</title>
                        </add>
                        <update translate="title" module="portfolio">
                            <title>Update</title>
                        </update>
                        <remove translate="title" module="portfolio">
                            <title>Remove</title>
                        </remove>
                    </project>
                </portfolio>
            </resources>
        </acl>
    </api>
</config>

app/code/local/Easylife/Portfolio/etc/wsdl.xml - wsdl part for V2

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"
    name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}">
    <types>
        <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento">
            <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" />
            <complexType name="portfolioProjectListEntity"><!-- define type for project list -->
                <all>
                    <element name="entity_id" type="xsd:string" minOccurs="1" />
                    <element name="name" type="xsd:string" minOccurs="1" />
                    <element name="description" type="xsd:string" minOccurs="0" />
                    <element name="status" type="xsd:string" minOccurs="0" />
                    <element name="created_at" type="xsd:string" minOccurs="1" />
                    <element name="updated_at" type="xsd:string" minOccurs="1" />
                </all>
            </complexType>
            <complexType name="portfolioProjectListEntityArray"><!-- define type array of projects -->
                <complexContent>
                    <restriction base="soapenc:Array">
                        <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:portfolioProjectListEntity[]" />
                    </restriction>
                </complexContent>
            </complexType>
            <complexType name="portfolioProjectAddEntity"><!-- define type for add project -->
                <all>
                    <element name="name" type="xsd:string" minOccurs="1" />
                    <element name="description" type="xsd:string" minOccurs="0" />
                    <element name="status" type="xsd:string" minOccurs="0" />

                </all>
            </complexType>
            <complexType name="portfolioProjectUpdateEntity"><!-- define type for update project -->
                <all>
                    <element name="name" type="xsd:string" minOccurs="1" />
                    <element name="description" type="xsd:string" minOccurs="0" />
                    <element name="status" type="xsd:string" minOccurs="0" />

                </all>
            </complexType>
            <complexType name="portfolioProjectInfoEntity"><!-- define type for retrieve info -->
                <all>
                    <element name="entity_id" type="xsd:string" minOccurs="1" />
                    <element name="name" type="xsd:string" minOccurs="1" />
                    <element name="description" type="xsd:string" minOccurs="0" />
                    <element name="status" type="xsd:string" minOccurs="0" />

                    <element name="created_at" type="xsd:string" minOccurs="1" />
                    <element name="updated_at" type="xsd:string" minOccurs="1" />
                </all>
            </complexType>
                </schema>
    </types>
    <!--[+] define messages -->
    <message name="portfolioProjectListRequest">
        <part name="sessionId" type="xsd:string" />
        <part name="filters" type="typens:filters"/>
    </message>
    <message name="portfolioProjectListResponse">
        <part name="result" type="typens:portfolioProjectListEntityArray" />
    </message>
    <message name="portfolioProjectInfoRequest">
        <part name="sessionId" type="xsd:string" />
        <part name="projectId" type="xsd:string" />
    </message>
    <message name="portfolioProjectInfoResponse">
        <part name="result" type="typens:portfolioProjectInfoEntity" />
    </message>
    <message name="portfolioProjectAddRequest">
        <part name="sessionId" type="xsd:string" />
        <part name="data" type="typens:portfolioProjectAddEntity" />
    </message>
    <message name="portfolioProjectAddResponse">
        <part name="result" type="xsd:int"/>
    </message>
    <message name="portfolioProjectUpdateRequest">
        <part name="sessionId" type="xsd:string" />
        <part name="projectId" type="xsd:string" />
        <part name="data" type="typens:portfolioProjectUpdateEntity" />
    </message>
    <message name="portfolioProjectUpdateResponse">
        <part name="result" type="xsd:boolean" />
    </message>
    <message name="portfolioProjectRemoveRequest">
        <part name="sessionId" type="xsd:string" />
        <part name="projectId" type="xsd:string" />
    </message>
    <message name="portfolioProjectRemoveResponse">
        <part name="result" type="xsd:boolean" />
    </message>
    <!--[-] define messages -->
    <!--[+] define portTypes -->
    <portType name="{{var wsdl.handler}}PortType">
        <operation name="portfolioProjectList">
            <documentation>Retrieve list of project</documentation>
            <input message="typens:portfolioProjectListRequest" />
            <output message="typens:portfolioProjectListResponse" />
        </operation>
        <operation name="portfolioProjectInfo">
            <documentation>Retrieve project info</documentation>
            <input message="typens:portfolioProjectInfoRequest" />
            <output message="typens:portfolioProjectInfoResponse" />
        </operation>
        <operation name="portfolioProjectAdd">
            <documentation>Add project</documentation>
            <input message="typens:portfolioProjectAddRequest" />
            <output message="typens:portfolioProjectAddResponse" />
        </operation>
        <operation name="portfolioProjectUpdate">
            <documentation>Update project</documentation>
            <input message="typens:portfolioProjectUpdateRequest" />
            <output message="typens:portfolioProjectUpdateResponse" />
        </operation>
        <operation name="portfolioProjectRemove">
            <documentation>Remove project</documentation>
            <input message="typens:portfolioProjectRemoveRequest" />
            <output message="typens:portfolioProjectRemoveResponse" />
        </operation>
    </portType>
    <!--[-] define portTypes -->
    <!--[+] define binding -->
    <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
        <operation name="portfolioProjectList">
            <soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
            <input>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </input>
            <output>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </output>
        </operation>
        <operation name="portfolioProjectInfo">
            <soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
            <input>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </input>
            <output>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </output>
        </operation>
        <operation name="portfolioProjectAdd">
            <soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
            <input>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </input>
            <output>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </output>
        </operation>
        <operation name="portfolioProjectUpdate">
            <soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
            <input>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </input>
            <output>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </output>
        </operation>
        <operation name="portfolioProjectRemove">
            <soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
            <input>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </input>
            <output>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </output>
        </operation>
    </binding>
    <!--[-] define portTypes -->
    <service name="{{var wsdl.name}}Service">
        <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding">
            <soap:address location="{{var wsdl.url}}" />
        </port>
    </service>
</definitions>

app/code/local/Easylife/Portfolio/etc/wsi.xml - it's similar to wsdl.xml but it's used for WS-I complience

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
     xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
     xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
     name="{{var wsdl.name}}"
     targetNamespace="urn:{{var wsdl.name}}">
    <wsdl:types>
        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}">
            <xsd:complexType name="portfolioProjectListEntityArray">
                <xsd:sequence>
                    <xsd:element maxOccurs="unbounded" name="complexObjectArray" type="typens:portfolioProjectListEntity" />
                </xsd:sequence>
            </xsd:complexType>
            <xsd:complexType name="portfolioProjectListEntity">
                <xsd:sequence>
                    <xsd:element name="entity_id" type="xsd:string" />
                    <xsd:element name="name" type="xsd:string" />
                    <xsd:element name="description" type="xsd:string" />
                    <xsd:element name="status" type="xsd:string" />

                    <xsd:element name="created_at" type="xsd:string" />
                    <xsd:element name="updated_at" type="xsd:string" />
                </xsd:sequence>
            </xsd:complexType>
            <xsd:complexType name="portfolioProjectAddEntity">
                <xsd:sequence>
                    <xsd:element name="name" type="xsd:string" />
                    <xsd:element name="description" type="xsd:string" />
                    <xsd:element name="status" type="xsd:string" />

                </xsd:sequence>
            </xsd:complexType>
            <xsd:complexType name="portfolioProjectUpdateEntity">
                <xsd:sequence>
                    <xsd:element name="name" type="xsd:string" />
                    <xsd:element name="description" type="xsd:string" />
                    <xsd:element name="status" type="xsd:string" />

                </xsd:sequence>
            </xsd:complexType>
            <xsd:complexType name="portfolioProjectInfoEntity">
                <xsd:sequence>
                    <xsd:element name="entity_id" type="xsd:string" />
                    <xsd:element name="name" type="xsd:string" />
                    <xsd:element name="description" type="xsd:string" />
                    <xsd:element name="status" type="xsd:string" />

                    <xsd:element name="created_at" type="xsd:string" />
                    <xsd:element name="updated_at" type="xsd:string" />
                </xsd:sequence>
            </xsd:complexType>

            <xsd:element name="portfolioProjectListRequestParam">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" />
                        <xsd:element minOccurs="0" maxOccurs="1" name="filters" type="typens:filters" />
                    </xsd:sequence>
                 </xsd:complexType>
            </xsd:element>
            <xsd:element name="portfolioProjectListResponseParam">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:portfolioProjectListEntityArray" />
                    </xsd:sequence>
                 </xsd:complexType>
            </xsd:element>
            <xsd:element name="portfolioProjectInfoRequestParam">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" />
                        <xsd:element minOccurs="1" maxOccurs="1" name="projectId" type="xsd:string" />
                    </xsd:sequence>
                 </xsd:complexType>
            </xsd:element>
            <xsd:element name="portfolioProjectInfoResponseParam">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:portfolioProjectInfoEntity" />
                    </xsd:sequence>
                 </xsd:complexType>
            </xsd:element>
            <xsd:element name="portfolioProjectAddRequestParam">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" />
                        <xsd:element minOccurs="1" maxOccurs="1" name="data" type="typens:portfolioProjectAddEntity" />
                    </xsd:sequence>
                 </xsd:complexType>
            </xsd:element>
            <xsd:element name="portfolioProjectAddResponseParam">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" />
                    </xsd:sequence>
                 </xsd:complexType>
            </xsd:element>
            <xsd:element name="portfolioProjectUpdateRequestParam">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" />
                        <xsd:element minOccurs="1" maxOccurs="1" name="projectId" type="xsd:string" />
                        <xsd:element minOccurs="1" maxOccurs="1" name="data" type="typens:portfolioProjectUpdateEntity" />
                    </xsd:sequence>
                 </xsd:complexType>
            </xsd:element>
            <xsd:element name="portfolioProjectUpdateResponseParam">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" />
                    </xsd:sequence>
                 </xsd:complexType>
            </xsd:element>
            <xsd:element name="portfolioProjectRemoveRequestParam">
                <xsd:complexType>
                    <xsd:sequence>
                    <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" />
                        <xsd:element minOccurs="1" maxOccurs="1" name="projectId" type="xsd:string" />
                    </xsd:sequence>
                 </xsd:complexType>
            </xsd:element>
            <xsd:element name="portfolioProjectRemoveResponseParam">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" />
                    </xsd:sequence>
                 </xsd:complexType>
            </xsd:element>
                </xsd:schema>
    </wsdl:types>
    <wsdl:message name="portfolioProjectListRequest">
        <wsdl:part name="parameters" element="typens:portfolioProjectListRequestParam" />
    </wsdl:message>
    <wsdl:message name="portfolioProjectListResponse">
        <wsdl:part name="parameters" element="typens:portfolioProjectListResponseParam" />
    </wsdl:message>
    <wsdl:message name="portfolioProjectInfoRequest">
        <wsdl:part name="parameters" element="typens:portfolioProjectInfoRequestParam" />
    </wsdl:message>
    <wsdl:message name="portfolioProjectInfoResponse">
        <wsdl:part name="parameters" element="typens:portfolioProjectInfoResponseParam" />
    </wsdl:message>
    <wsdl:message name="portfolioProjectAddRequest">
        <wsdl:part name="parameters" element="typens:portfolioProjectAddRequestParam" />
    </wsdl:message>
    <wsdl:message name="portfolioProjectAddResponse">
        <wsdl:part name="parameters" element="typens:portfolioProjectAddResponseParam"/>
    </wsdl:message>
    <wsdl:message name="portfolioProjectUpdateRequest">
        <wsdl:part name="parameters" element="typens:portfolioProjectUpdateRequestParam" />
    </wsdl:message>
    <wsdl:message name="portfolioProjectUpdateResponse">
        <wsdl:part name="parameters" element="typens:portfolioProjectUpdateResponseParam"/>
    </wsdl:message>
    <wsdl:message name="portfolioProjectRemoveRequest">
        <wsdl:part name="parameters" element="typens:portfolioProjectRemoveRequestParam" />
    </wsdl:message>
    <wsdl:message name="portfolioProjectRemoveResponse">
        <wsdl:part name="parameters" element="typens:portfolioProjectRemoveResponseParam" />
    </wsdl:message>
    <wsdl:portType name="{{var wsdl.handler}}PortType">
        <wsdl:operation name="portfolioProjectList">
            <wsdl:documentation>Retrieve list of projects</wsdl:documentation>
            <wsdl:input message="typens:portfolioProjectListRequest" />
            <wsdl:output message="typens:portfolioProjectListResponse" />
        </wsdl:operation>
        <wsdl:operation name="portfolioProjectInfo">
            <wsdl:documentation>Retrieve project info</wsdl:documentation>
            <wsdl:input message="typens:portfolioProjectInfoRequest" />
            <wsdl:output message="typens:portfolioProjectInfoResponse" />
        </wsdl:operation>
        <wsdl:operation name="portfolioProjectAdd">
            <wsdl:documentation>Add project</wsdl:documentation>
            <wsdl:input message="typens:portfolioProjectAddRequest" />
            <wsdl:output message="typens:portfolioProjectAddResponse" />
        </wsdl:operation>
        <wsdl:operation name="portfolioProjectUpdate">
            <wsdl:documentation>Update project</wsdl:documentation>
            <wsdl:input message="typens:portfolioProjectUpdateRequest" />
            <wsdl:output message="typens:portfolioProjectUpdateResponse" />
        </wsdl:operation>
        <wsdl:operation name="portfolioProjectRemove">
            <wsdl:documentation>Remove project</wsdl:documentation>
            <wsdl:input message="typens:portfolioProjectRemoveRequest" />
            <wsdl:output message="typens:portfolioProjectRemoveResponse" />
        </wsdl:operation>
        </wsdl:portType>
    <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="portfolioProjectList">
            <soap:operation soapAction="" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="portfolioProjectInfo">
            <soap:operation soapAction="" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="portfolioProjectAdd">
            <soap:operation soapAction="" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="portfolioProjectUpdate">
            <soap:operation soapAction="" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="portfolioProjectRemove">
            <soap:operation soapAction="" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        </wsdl:binding>
    <wsdl:service name="{{var wsdl.name}}Service">
        <wsdl:port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding">
            <soap:address location="{{var wsdl.url}}" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

The example did not fit in one answer. See the rest of the files here


Note: These files were created using the Ultimate Module Creator. I've just added some comments in the xml files.

Related Topic