Back to blog home

Magento 2 tutorial: an overview of the Web API

This Magento 2 tutorial looks at the Web API. Web services are a key feature for integrating your Magento 2 application with external systems. The changes Magento 2 has made in this area now make it much easier for developers to create integration points.

This article assumes some familiarity with SOAP and REST, so if you are unfamiliar with either it would help to gain a background understanding before reading on.

Web API changes at a glance

Magento 1 Magento 2
Different feature coverage between SOAP and REST Same features exposed to SOAP and REST
Separate code for SOAP and REST Same module exposes Magento 2 service contracts to SOAP and REST
Different authentication systems used by SOAP and REST Compatible token authentication system used by SOAP and REST (OAuth still used by REST only)
SOAP WS-I compliance optional SOAP WS-I compliant only
No automatic customer/admin session based authentication Automatic customer/admin session based authentication
No unauthenticated access allowed Unauthenticated access allowed

Web API: overview

There were quite a few problems with the Web API in Magento 1, which can be summarised as inconsistency issues for the most part.

The REST API was added in version 1.12 EE (1.7 CE) and only covered a subset of the features of the established SOAP API. Its code was separate too, as were the XML and admin configuration options and the permission levels. Additionally, it had a separate OAuth authentication mechanism, making it a great deal more complex to use than the SOAP API.

The SOAP API also had its quirks, with WS-I compliance being added as an option in the V2 API to make it compatible with Java and .NET implementations. Combined with the deprecated V1 API this meant that by 1.14 EE (1.9 CE) there were three different ways to write a SOAP script.

Magento 2 has seen an overhaul of the Web API and the theme now is consistency and interoperability. The SOAP and REST APIs have access to the same features, use the same permissions, and can share authentication. Additionally, the SOAP API is now universally WS-I compliant.

Perhaps the biggest change conceptually, however, is the introduction of ‘Integrations’, which are intended to represent third-party integration points. They allow for separate permission allocation and separate authorisation using OAuth. They can be managed in the admin area at System > Integrations. But more on Integrations and OAuth later!

Routes

Defining Web API routes in Magento 2 is much simpler when compared with Magento 1. The routes are defined in etc/webapi.xml within a module, and although the structure of the definition xml is directed by the requirements of the REST API, the SOAP API uses the same definitions.

Configuration

The following shows the route configuration for fetching a CMS block, as defined in Magento_Cms::etc/webapi.xml:

...
    <route url="/V1/cmsBlock/:blockId" method="GET">
        <service class="Magento\Cms\Api\BlockRepositoryInterface" method="getById"/>
        <resources>
            <resource ref="Magento_Cms::block"/>
        </resources>
    </route>
    ...

In the route tag the url attribute defines the route as /V1/cmsBlock/:blockId where the :blockId part represents an id parameter to be supplied. The method attribute defines the HTTP verb the route uses as ‘GET’ (other available verbs are PUT, POST and DELETE).

In the service tag the class attribute associates the service contract Magento\Cms\Api\BlockRepositoryInterface with the route, and the method attribute defines the method to call upon the object provided by the service contract.

The resources and resource tags are further explained in the permissions section coming up.

Accessing routes

As mentioned above, the configuration is conveniently used by both the REST and SOAP APIs. However, the means of accessing resources differs quite a lot.

The full REST resource URL is the easiest to determine as it just needs prefixing with ‘http://www.yourdomain.com/rest/’, so in the example above, assuming the block needed has an entity id of 1, the resource url would be ‘http://www.yourdomain.com/rest/V1/cmsBlock/1’.

For SOAP the process is a bit more complicated. In Magento 1 the WSDL was a monolithic file, but in Magento 2 it has been broken down, with a WSDL representing each service contract. You can get a list of available WSDLs at ‘http://www.yourdomain.com/soap/default?wsdl_list’:

The screenshot shows the WSDL list, with the endpoint URL for the CMS block service highlighted.

If the endpoint ‘http://magento2ee.dev/soap/default?wsdl&services=cmsBlockRepositoryV1’ is followed we see the following:

This shows part of the CMS block WSDL with some useful information highlighted in relation to the route configuration discussed above. The bottom highlighted element shows what SOAP call name needs to be used and the top highlighted element shows the parameter required. The usage of this information will be demonstrated in the authentication section below.

REST API route discovery

As you can see in the section above, one of the advantages of the SOAP API is that the WSDL makes it self-documenting. However, in Magento 2 it is now possible to view all the available REST resources using documentation generated by Swagger UI. If you just need to look at a reference for what is available in the Community Edition (CE) core then visit http://devdocs.magento.com/swagger/index.html.

The top screenshot above shows the documentation with a section expanded to show a set of routes related by service contract. Each route can be further expanded to get more information. The screenshot below that shows the CMS block route discussed earlier, along with the additional routes that use the same service contact.

There are situations where you may need to view the available REST resources for your installation, such as when you have added customisations, when the version you are using is behind the latest, or when you are using Enterprise Edition (EE). For this you can get a Swagger UI compatible JSON file by requesting ‘http://www.yourdomain.com/rest/default/schema’.

On its own the JSON is not very accessible, but it’s not too difficult to use git to clone Swagger UI and get it to format the output for you.

First, clone the Swagger UI repo on github to your prefered location (here I’ve just used my home directory), then switch into the dist directory:

> cd ~
> git clone git@github.com:swagger-api/swagger-ui.git
> cd swagger-ui/dist

Then, to avoid cross origin HTTP request issues, we’ll get a copy of the JSON Swagger file:

> curl http://www.yourdomain.com/rest/default/schema -o m2-rest.json

Then fire up a built-in PHP web server:

> php -S localhost:8081

Then, all being well, you should be able enter the URL ‘http://localhost:8081/?url=http://localhost:8081/m2-rest.json’ into your browser and see the generated documentation:

As you can see, the resultant output is very similar to the official documentation described above, but will reflect your local instance instead.

Permissions

Assigned permissions

In Magento 2 permissions have also been simplified and can be defined and configured in 'etc/acl.xml and etc/webapi.xml' within a module. Permissions defined in this way are assignable to either an admin user role or an Integration using the admin interface.

The following shows the customer ACL permission definition from Magento_Customer::etc/acl.xml:

...
    <acl>
        <resources>
            <resource id="Magento_Backend::admin">
                <resource id="Magento_Customer::customer" title="Customers" sortOrder="40">
                ...
                </resource>
            ...
            </resource>
        </resources>
    </acl>
    ...

This adds a ‘Magento_Customer::customer’ permission to the tree of available permissions, which is presented to an administrator when creating an admin user role or creating an Integration. See Fig. 3 in the ‘Setting up an Integration’ section below for a screenshot of this process.

The following shows the customer route configuration from Magento_Customer::etc/webapi.xml:

...
    <route url="/V1/customers/:customerId" method="GET">
        <service class="Magento\Customer\Api\CustomerRepositoryInterface" method="getById"/>
        <resources>
            <resource ref="Magento_Customer::customer"/>
        </resources>
    </route>
    ...

Within the resources tag is a resource tag, and in that the ref attribute associates the ‘Magento_Customer::customer’ permission with the customer route. Only admin users and Integrations with the Magento_Customer::customer permission assigned will be able to access this.

Assigned permissions are stored in the database tables authorization_role and authorization_rule, which are shared by admin roles and Integrations. Although they are presented in a tree format when they are shown in the admin interface, they are stored in a single column in the authorization_rule table, so when defining them they need to be unique (hence the convention of prefixing with the module name to avoid collisions).

Special permissions

Magento 2 also introduces two more special permissions which can be referenced in a resource tag, and these are ‘self’ and ‘anonymous’. The following shows these two permissions in Magento_Customer::etc/webapi.xml.

  …
    <route url="/V1/customers/me" method="GET">
        <service class="Magento\Customer\Api\CustomerRepositoryInterface" method="getById"/>
        <resources>
            <resource ref="self"/>
        </resources>
        <data>
            <parameter name="customerId" force="true">%customer_id%</parameter>
        </data>
    </route>
    …
    <route url="/V1/customers" method="POST">
        <service class="Magento\Customer\Api\AccountManagementInterface" method="createAccount"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
    ...

In the example above the ‘self’ permission allows a customer to access the /V1/customers/me route and retrieve information about itself only. In the handling code the PHP session cookie is used to verify that the customer is legitimate and matches the supplied customer_id parameter. Session authentication is discussed further below.

Also, in the example above, the ‘anonymous’ permission, as its name suggests, allows access to the /V1/customers route – even for a user who’s not logged-in. The route is used to create a customer when data is posted to it, so it makes sense that access needs to be open. This might seem like a security risk, but the POST data also requires a valid form key to process the request.

Summary of permissions

The table below summarises user types and the permission types available to them.

User Type

Description

Permission Type

Integration A third-party application As assigned to Integration e.g. ‘Magento_Cms::block’. Also ‘self’ or ‘anonymous’.
Administrator A user with an admin account As assigned to linked admin role e.g. ‘Magento_Cms::page’. Also ‘self’ or ‘anonymous’.
Customer A user with a customer account ‘self’ or ‘anonymous’
Guest A user without any account ‘anonymous’

 

As you can see, permissions cascade, so Integrations and Administrators both have access to Customer and Guest resources, and Customers have access to Guest resources.

Authentication

There are three authentication methods available when using the Web API: token-based, OAuth-based, and session-based. The following table gives an idea of where they get used and whether they can be used by SOAP or REST.

Authentication Type Purpose SOAP REST
Token Mobile application Yes Yes
OAuth Third-party application (integration) No Yes
Session Javascript application on the frontend site or admin site Yes Yes

Token authentication

Token authentication can be used with both SOAP and REST. It allows a token to be requested using either an administrator or customer username/password combination. This token is then supplied in subsequent requests in a Authorization HTTP header.

The example below shows what an token Authorization HTTP header looks like:

Authorization: Bearer ifwkyqwg27got0x3h6yyofrhn6kb5wuq

The token request service uses an ‘anonymous’ route to allow an application to make the initial request for a token. This can be seen in Magento_Integration::etc/webapi.xml:

    …
   <route url="/V1/integration/admin/token" method="POST">
        <service class="Magento\Integration\Api\AdminTokenServiceInterface" method="createAdminAccessToken"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
    <route url="/V1/integration/customer/token" method="POST">
        <service class="Magento\Integration\Api\CustomerTokenServiceInterface" method="createCustomerAccessToken"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
    ...

Here we can see two ‘anonymous’ routes set up. The first allows admin user credentials to be supplied to get access permissions at the level assigned to that admin user. The second allows customer credentials to be supplied to get access permission at customer scope level (which gives access to ‘self’ and ‘anonymous’ routes).

Now let’s put all this together and demonstrate how to use tokens practically.

SOAP script using token

Note: the following script has been added to GitHub and annotated to avoid making this tutorial too long!

The following is a link to a basic PHP script that requests a CMS block using token authentication with SOAP: https://github.com/inviqa/inviqa-blog-code-samples/blob/master/magento2/WebApiExample/soap-token-example.php.

Let’s try and break that down to make it easier to understand.

Reference Description
Lines 4-5 Define the endpoints for the token service and CMS block service respectively.
Lines 6-7 Define the username and password to be supplied to the token service.
Lines 9-13 Define some basic options to be supplied to the PHP SoapClient.
Lines 17-24 Use the SoapClient to access the anonymous token resource and retrieve a token.
Lines 28-32 Add the bearer token to an ‘Authorization’ header in the SoapClient options.
Lines 36-42 Use the SoapClient to access the CMS block service to retrieve the block content.

REST script using token

Note: the following script has been added to GitHub and annotated to avoid making this tutorial too long!

And here is a script that does exactly the same thing, using token authentication with REST instead: https://github.com/inviqa/inviqa-blog-code-samples/blob/master/magento2/WebApiExample/rest-token-example.php.

Again, it needs breaking down a bit:

Reference Description
Line 3 Link to the composer autoloader, as the script needs to make use of the Zend Http library components. If you are running this script locally you will need to adjust this to point to the vendor directory of your own Magento 2 install.
Lines 5-8 Load the Zend Http classes needed.
Lines 12-13 Define the endpoints for the token service and CMS block service respectively.
Lines 14-15 Define the username and password to be supplied to the token service.
Lines 19-22 Create a headers object and set the Content-Type to ‘application/json’ so that the REST server knows that JSON will be sent in the request.
Lines 23-27 Create a request object and add the headers object to it. Additionally set the token service URL, set the HTTP verb to POST and add the username and password to the request body in JSON format.
Lines 31-42 Create a client object and use it to send the request and get a response, which contains the token.
Lines 46-50 Create a headers object as above, but crucially the token is added to it in an Authorization header.
Lines 51-54 Create a new request object for the CMS block service and add the headers object.
Lines 58-67 Create a new client object and used to send the request and get a response containing the CMS block content.

OAuth authentication

OAuth authentication is similar to the token method in that it uses an Authorization HTTP header, but instead of using a bearer token it supplies a more complex arrangement of OAuth tokens.

OAuth authentication is in theory supported for both SOAP and REST. However, in practice SOAP doesn’t seem to work, returning authorisation errors. The official documentation never explicitly says that SOAP isn’t supported but all the OAuth examples use REST.

The example below shows what an OAuth Authorization header looks like:

Authorization: OAuth oauth_consumer_key="vt05sufcppvlxjhl37baqnawk3vx56m4",
oauth_token="cf14inbog1npxp0qro3w20l4onfkpa42",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1465992492",
oauth_nonce="PQ86Ob",
oauth_version="1.0",
oauth_signature="ucFj73HF1unYELRaRgVIe5uwDFM%3D"

Setting up an Integration

OAuth authentication is applicable only when working with Integrations. So in order to write a test script using OAuth, an Integration needs to be created with which to interact. The instructions below step through this:

Step 1

Go to System > Integrations and clicking on the ‘Add New Integration’ button.

Step 2

Description: You should initially see the default ‘Integration Info’ tab where you need to enter a name for the test Integration.

For a full integration this would be the time to also enter the ‘Callback URL’ and ‘Identity link URL’, however for testing purposes these can be skipped.

Step 3

Decription: You then need to switch to the ‘API’ tab and select some applicable resources, ensuring, at the very least, that Content > Elements > Blocks is selected.

For a full integration a similar approach should be taken i.e. selecting only the resources that are needed.

Now click the ‘Save’ button.

Step 4

You should now see the new Integration listed. However, you will see that the status of the new Integration is ‘Inactive’. To change this (and generate the OAuth access tokens) you need to click ‘Activate’.

Step 5

This will prompt a modal window asking you to approve the permissions assigned to the Integration. Click the ‘Allow’ button.

Step 6

This will prompt a further modal displaying the newly generated access tokens. Now click ‘Done’.

Step 7

The Integration now has a status of ‘Active’ and is ready to use.

If you didn’t capture the access tokens in the screen above, you can view them again by editing the Integration.

REST script using OAuth

Note: the following script has been added to GitHub and annotated to avoid making this tutorial too long!

With an Integration now set up, here is a script that does the same thing as the token authentication scripts, using OAuth authentication with REST instead: https://github.com/inviqa/inviqa-blog-code-samples/blob/master/magento2/WebApiExample/rest-oauth-example.php.

Again, it needs breaking down a bit. To avoid repetition, lines similar to the REST script in the previous section will not be annotated.

Reference Description
Lines 5-7 Load the OAuth classes needed.
Lines 17-24 Define the values needed by OAuth, including the token values generated when creating the Integration above.
Lines 28-35 Assign OAuth values into a params array.
Lines 37-43 Generate OAuth signature.
Line 44 Add signature to params array.
Lines 48-58 Create a headers object using the params array to generate an OAuth Authorization header.
Lines 62-65 Create a new request object for the CMS block service and add the headers object.
Lines 69-78 Create a new client object and used to send the request and get a response containing the CMS block content.

Session authentication

Session authentication uses the PHP session to determine if the request has originated from a browser where a customer is logged in, and as such no Authorization HTTP header needs to be sent. 

Session authentication is supported for both SOAP and REST. However, in practice REST is the more convenient option, and this is reflected in the core code where only REST is used. 

The main purpose of session authentication is to allow Javascript widgets to be able to easily get information about the application.

Below is an example of a route that will return details of the currently logged in customer.

<route url="/V1/customers/me" method="GET">
        <service class="Magento\Customer\Api\CustomerRepositoryInterface" method="getById"/>
        <resources>
            <resource ref="self"/>
        </resources>
        <data>
            <parameter name="customerId" force="true">%customer_id%</parameter>
        </data>
    </route>

As you can see, it uses ‘self’ in relation to the resource which means it will have session level authentication. The route uses the word ‘me’ to further distinguish it as a customer specific route (the convention is to use either ‘me’ or ‘mine’ in these routes).

You can very easily use cURL to emulate your browser to see the session authentication in action. The only prerequisite is to log in to your Magento 2 instance and get hold of the PHPSESSID cookie value:

In the screenshot above I’ve logged in with the default Magento 2 user and have used the dev tools to find the PHPSESSID, which has a value of ‘qm4ktqfbeo37473r0tglgki5h7’.

Then from the command line, the following command can be run:
 

> curl 'http://magento2ee.dev/rest/default/V1/customers/me' \
-H 'Cookie:  PHPSESSID=qm4ktqfbeo37473r0tglgki5h7;' \
-H 'Content-Type: application/json' \
-H 'X-Requested-With: XMLHttpRequest'

If the session is still active, a JSON dataset for the customer should be returned:

{  
   "id":1,
   "group_id":1,
   "default_billing":"1",
   "default_shipping":"1",
   "created_at":"2016-03-07 16:27:58",
   "updated_at":"2016-03-07 16:27:59",
   "created_in":"Default Store View",
   "dob":"1973-12-15",
   "email":"roni_cost@example.com",
   "firstname":"Veronica",
   "lastname":"Costello",
   "gender":2,
   "store_id":1,
   "website_id":1,
   "addresses":[  
      ...
   ]
}

Further reading

The following resources were extremely helpful when writing this blog and provide additional insights into the Web API.

Getting Started with Magento Web APIs

Magento 2 REST API swagger schema

Magento 2: Understanding the Web API Architecture
 

About the author

Phillip has more than 13 years of experience designing and building web applications. He has spent last five of these working exclusively on Magento projects at Inviqa. Prior to this, Phillip worked in a variety of roles including server- and client-side development, client- / server-side integration and interface design.