Skip to content
intermediate Phase 16 · Adminhtml, Web API & Cron Areas

Magento 2 Web API Area

Web API area - REST routes, GraphQL, service contracts exposed via API, and webapi.xml configuration.

45m
0 problems
Topic Progress 0%

Web API Architecture

Magento 2 provides two API interfaces: REST and GraphQL. Both are handled through the Web API area, which loads when API requests are detected.

Web API Area Files:

app/code/Vendor/Module/etc/
├── webapi.xml          # REST route definitions
├── webapi_graphql/
│   └── schema.graphql  # GraphQL type definitions
├── webapi_rest/
│   └── di.xml          # REST-specific DI
└── webapi_graphql/
    └── di.xml          # GraphQL-specific DI

Service Contract Pattern:
The Web API exposes service contracts - PHP interfaces that define business operations. Service contracts decouple API logic from implementation.

app/code/Vendor/Module/Api/
├── Data/
│   └── ItemInterface.php      # Data transfer object interface
├── ItemRepositoryInterface.php # CRUD operations
└── ItemManagementInterface.php # Business logic operations

When a REST request arrives:

  1. Area code set to webapi_rest
  2. webapi.xml routes matched against the URL
  3. Service class instantiated via DI
  4. Method called with parameters from request body
  5. Response serialized as JSON

For GraphQL:

  1. Area code set to webapi_graphql
  2. Schema parsed from schema.graphql
  3. Resolver class handles the query
  4. Response follows GraphQL response format

REST Routes with webapi.xml

REST API routes are defined in webapi.xml using a resource-based approach.

<!-- app/code/Vendor/Module/etc/webapi.xml -->
<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
    
    <!-- GET - Retrieve item -->
    <route url="/V1/items/:itemId" method="GET">
        <service class="Vendor\Module\Api\ItemRepositoryInterface" method="getById"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
    
    <!-- POST - Create item -->
    <route url="/V1/items" method="POST">
        <service class="Vendor\Module\Api\ItemRepositoryInterface" method="save"/>
        <resources>
            <resource ref="Vendor_Module::items_manage"/>
        </resources>
    </route>
    
    <!-- PUT - Update item -->
    <route url="/V1/items/:itemId" method="PUT">
        <service class="Vendor\Module\Api\ItemRepositoryInterface" method="save"/>
        <resources>
            <resource ref="Vendor_Module::items_manage"/>
        </resources>
    </route>
    
    <!-- DELETE - Delete item -->
    <route url="/V1/items/:itemId" method="DELETE">
        <service class="Vendor\Module\Api\ItemRepositoryInterface" method="deleteById"/>
        <resources>
            <resource ref="Vendor_Module::items_manage"/>
        </resources>
    </route>
    
    <!-- Custom action -->
    <route url="/V1/items/:itemId/activate" method="POST">
        <service class="Vendor\Module\Api\ItemManagementInterface" method="activate"/>
        <resources>
            <resource ref="Vendor_Module::items_manage"/>
        </resources>
    </route>
</routes>

URL Parameters:

  • :parameterName - Required path parameter
  • {parameterName} - Optional query parameter

Resource References:

  • anonymous - No authentication required
  • self - User can only access own resources
  • Magento\InventoryApi::... - Module-specific ACL resource

Service Contract Implementation

Service contracts are PHP interfaces that define how external systems interact with your module.

Data Interface:

<?php
namespace Vendor\Module\Api\Data;

interface ItemInterface
{
    const ENTITY_ID = 'entity_id';
    const NAME = 'name';
    const STATUS = 'status';
    const CREATED_AT = 'created_at';
    
    public function getEntityId(): ?int;
    public function setEntityId(int $id): ItemInterface;
    
    public function getName(): ?string;
    public function setName(string $name): ItemInterface;
    
    public function getStatus(): ?int;
    public function setStatus(int $status): ItemInterface;
}

Repository Interface:

<?php
namespace Vendor\Module\Api;

use Vendor\Module\Api\Data\ItemInterface;

interface ItemRepositoryInterface
{
    public function getById(int $itemId): ItemInterface;
    
    public function save(ItemInterface $item): ItemInterface;
    
    public function delete(ItemInterface $item): bool;
    
    public function deleteById(int $itemId): bool;
    
    public function getList(
        \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
    ): \Magento\Framework\Api\SearchResultsInterface;
}

Repository Implementation:

<?php
namespace Vendor\Module\Model;

use Vendor\Module\Api\ItemRepositoryInterface;
use Vendor\Module\Api\Data\ItemInterface;
use Vendor\Module\Model\ResourceModel\Item as ItemResource;

class ItemRepository implements ItemRepositoryInterface
{
    private $resource;
    private $itemFactory;
    private $searchResultsFactory;
    
    public function __construct(
        ItemResource $resource,
        \Vendor\Module\Model\ItemFactory $itemFactory,
        \Magento\Framework\Api\SearchResultsFactory $searchResultsFactory
    ) {
        $this->resource = $resource;
        $this->itemFactory = $itemFactory;
        $this->searchResultsFactory = $searchResultsFactory;
    }
    
    public function getById(int $itemId): ItemInterface
    {
        $item = $this->itemFactory->create();
        $this->resource->load($item, $itemId);
        if (!$item->getId()) {
            throw new \Magento\Framework\Exception\NoSuchEntityException(
                __('Item with id %1 does not exist.', $itemId)
            );
        }
        return $item;
    }
}

GraphQL Schema and Resolvers

GraphQL in Magento 2 uses schema definitions and resolver classes to handle queries and mutations.

GraphQL Schema:

# app/code/Vendor/Module/etc/webapi_graphql/schema.graphql
type Query {
    vendorItem(id: Int!): VendorItem @resolver(class: "Vendor\\Module\\GraphQl\\ItemResolver")
    vendorItems(searchCriteria: VendorItemSearchInput): VendorItemSearchResult
        @resolver(class: "Vendor\\Module\\GraphQl\\ItemSearchResolver")
}

type Mutation {
    createVendorItem(input: VendorItemInput!): VendorItem
        @resolver(class: "Vendor\\Module\\GraphQl\\ItemCreateResolver")
}

type VendorItem {
    id: Int!
    name: String!
    status: Int!
    created_at: String
}

input VendorItemInput {
    name: String!
    status: Int
}

input VendorItemSearchInput {
    page_size: Int
    current_page: Int
}

type VendorItemSearchResult {
    items: [VendorItem!]!
    total_count: Int
}

Resolver Class:

<?php
namespace Vendor\Module\GraphQl;

use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Vendor\Module\Api\ItemRepositoryInterface;

class ItemResolver
{
    private $itemRepository;
    
    public function __construct(ItemRepositoryInterface $itemRepository)
    {
        $this->itemRepository = $itemRepository;
    }
    
    public function resolve(
        Field $field,
        $context,
        ResolveInfo $info,
        array $value = null,
        array $args = null
    ) {
        $item = $this->itemRepository->getById($args['id']);
        return [
            'id' => $item->getEntityId(),
            'name' => $item->getName(),
            'status' => $item->getStatus(),
            'created_at' => $item->getCreatedAt(),
        ];
    }
}

GraphQL queries:

query {
    vendorItem(id: 1) {
        id
        name
        status
    }
}

Quiz

1. Which file defines REST API routes in Magento 2?

Question 1 options

2. What does the 'anonymous' resource reference mean in webapi.xml?

Question 2 options

3. What naming convention do GraphQL schema files follow?

Question 3 options

Flashcards

Question

What is the URL format for Magento 2 REST APIs?

Answer

/rest/{storeCode}/V1/{resource} (e.g., /rest/default/V1/items/1)

Question

What interface must repository classes implement?

Answer

Repository interfaces in the module's Api/ directory (e.g., ItemRepositoryInterface)

Question

How do GraphQL resolvers reference schema types?

Answer

Via @resolver(class: "Namespace\\Module\\GraphQl\\ResolverClass") annotation

Question

What does setup:di:compile generate for service contracts?

Answer

Proxy and factory classes for all service interfaces

Revision Notes

Key Takeaways

  • 1. Web API uses service contracts (interfaces) to define API methods
  • 2. REST routes defined in etc/webapi.xml with resource-based access control
  • 3. GraphQL uses schema.graphql files and resolver classes
  • 4. Service contracts decouple API from implementation details
  • 5. anonymous resource allows unauthenticated access
  • 6. Both REST and GraphQL share the same service layer

Interview Tips

  • Explain the service contract pattern and why it's important
  • Describe how to create a custom REST API endpoint
  • Discuss the difference between REST and GraphQL approaches
  • Explain how authentication works in Magento APIs
  • Know the webapi.xml structure and resource references

Cheat Sheet

Web API Cheat Sheet

REST Config: etc/webapi.xml
GraphQL Config: etc/webapi_graphql/schema.graphql
Service Layer: Api/ directory interfaces

Route Pattern:

<route url="/V1/items/:id" method="GET">
    <service class="Vendor\Module\Api\ItemRepositoryInterface" method="getById"/>
    <resources><resource ref="anonymous"/></resources>
</route>

GraphQL Query:

query { vendorItem(id: 1) { id name } }

Access Levels:

  • anonymous → No auth
  • self → Own resources
  • ACL resource → Permission required