Blog

Flexible APIs

Creating a generic API response for Magento 2

  • Magento Version: 2.2.3
  • Assumed Knowledge Level: Intermediate

This article was inspired by a particular problem I had in a client project recently. I was tasked with writing an API that required all the returned data to follow a strict structure. So I held my breath, and took a dive into the Magento 2 dev docs. What I found was that Magento’s API request protocols allow for the return of all scalar types such as ints, string, arrays, but it also supports returning objects with the use of interfaces . At first glance then, this task would can seem like a trivial matter, and you’re probably thinking “So what?”  For example if I were writing an API that returns customers I would declare a return type of say an array of customer interfaces and call it a day.

But what if we’re dealing with multiple model types?

It can be cumbersome to have to declare specific return types for each of your API calls if you are dealing with multiple different models, or worse, you’re not sure what models are going to be needed to be returned from your API as the project grows. For example, if we were building a blog inside our Magento store, here we could be dealing with posts, customers, comments, likes, notifications etc.; as well as potentially any of Magento’s own model types. Magento’s API protocol is very strict when declaring what type of data your API calls should return, and when we’re dealing with objects Magento expects an interface of that model as the declared return type. That means we would we need to write interfaces for each of the models returned in all of all of our API calls: no thanks! What if we wanted a generic return type that could handle any model we throw at it? This would also provide the added bonus of being consistently structured, so that anyone who wants to use it has a consistent experience. Read on and you’ll see my solution to this problem.

Generic Response Object

Note the @api tag in the block comments above the interface declaration. This tells Magento2 to use this when describing our API in the WYSIWIG (if you’re using SOAP).

Firstly let’s create our generic response object. This is going to be what we tell any of our API calls to return which will comply with Magento’s API protocol. We start with writing its interface; this is what we declare as the return type for any of our API requests. Magento 2 will read this when running through its API protocol and check that all return types in this interface are allowed.


Next, we’ll declare our concrete class that implements this interface.

Usage

Now we have a generic return type of any API call we write with the benefit of having a consistent response for anyone who wants to use our modules API. For example from my previous blog post I created a simple CRUD module that created notes. Building on that example, let’s register an API endpoint in our webapi.xml file for Magento to reference.


Now we write out our Note Repository class that our new end point references.



Now if we run a quick GET request to our new API endpoint to get a note with the ID of 1:

https://YOUR SITE DOMAIN/rest/V1/crud/notes/getById/1

Then our user will be greeted with the following response in some prettily formatted JSON:

{
    "message": "Note retrieved!",
    "response_data": [
         {
            "note_id": 1,
            "body": "Lorem Ipsum",
            "created_at": "2018-06-22 14:07:20",
            "updated_at": "2018-06-22 14:07:20"
        }
    ]
}

This approach allows us now to return any object we like in the response data key. It provides all the flexibility we need to write our API return types as well as a consistent response object for any poor soul that wants to use our API. A consistent response structure is particularly appreciated when dealing with mobile application or frontend development, where the developer on the other side just wants the data in a structured object, and lets them write a single handler for any response our API can throw at them. This in turn helps speed up the development process, as well as making life for the developer on the other end more bearable.

If you have any constructive feedback please leave a comment below. Our aim here is to provide solutions we’ve come up with to problems we’ve faced, but if you have a better solution don’t be shy to let us know!

About the author

Team C3