Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

The Web Services API

Joomla serves data not only as HTML pages but also through an API — as JSON, for mobile apps and for exchanging data with other systems. The API has its own entry point, api/index.php, and its own third part of a component in the api folder. First we look at the built-in API, then add blog posts to it.

The built-in API

RequestWhat it does
GET /api/index.php/v1/content/articlesThe list of articles
GET /api/index.php/v1/content/articles/1One article
POST /api/index.php/v1/content/articlesCreate an article
PATCH /api/index.php/v1/content/articles/1Change an article
DELETE /api/index.php/v1/content/articles/1Delete an article

The token

API requests are signed with a token. In the panel open your profile (Users → Manage, then your own account), the Joomla API Token tab, and copy the token. The plugins "API Authentication - Web Services Joomla Token" and "User - Joomla API Token" must be enabled.

curl http://joomla.test/api/index.php/v1/content/articles \
  -H "X-Joomla-Token: your_token"

The response is JSON with the list of articles. The request runs with the permissions of the token owner.

What your own component needs

plugins/webservices/hello/               the plugin: declares the addresses
├── hello.xml
├── services/provider.php
└── src/Extension/Hello.php
 
api/components/com_hello/                the API part of the component
└── src/
    ├── Controller/
    │   └── PostsController.php
    └── View/
        └── Posts/
            └── JsonapiView.php

All files are created by hand. Add a section to the component manifest:

<!-- administrator/components/com_hello/hello.xml -->
<api>
    <files folder="api">
        <folder>src</folder>
    </files>
</api>

The plugin with routes

The plugin manifest and provider are the same as for the content plugin, only with the webservices group and the namespace My\Plugin\WebServices\Hello. The class:

// plugins/webservices/hello/src/Extension/Hello.php
namespace My\Plugin\WebServices\Hello\Extension;
 
defined('_JEXEC') or die;
 
use Joomla\CMS\Event\Application\BeforeApiRouteEvent;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\SubscriberInterface;
 
final class Hello extends CMSPlugin implements SubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            'onBeforeApiRoute' => 'registerRoutes',
        ];
    }
 
    public function registerRoutes(BeforeApiRouteEvent $event): void
    {
        $event->getRouter()->createCRUDRoutes(
            'v1/hello/posts',
            'posts',
            ['component' => 'com_hello'],
        );
    }
}

createCRUDRoutes() declares five addresses at once: list, single record, create, change, delete. The second argument is the controller name. The BeforeApiRouteEvent event class exists in Joomla 5; in Joomla 4 the handler receives the router as an argument.

The controller

// api/components/com_hello/src/Controller/PostsController.php
namespace My\Component\Hello\Api\Controller;
 
defined('_JEXEC') or die;
 
use Joomla\CMS\MVC\Controller\ApiController;
 
class PostsController extends ApiController
{
    protected $contentType = 'posts';
    protected $default_view = 'posts';
}

All the work is already written in ApiController. It takes models from the administrator part of the component: PostsModel for the list and PostModel for a single record.

The view

// api/components/com_hello/src/View/Posts/JsonapiView.php
namespace My\Component\Hello\Api\View\Posts;
 
defined('_JEXEC') or die;
 
use Joomla\CMS\MVC\View\JsonApiView as BaseApiView;
 
class JsonapiView extends BaseApiView
{
    protected $fieldsToRenderList = ['id', 'title', 'created'];
    protected $fieldsToRenderItem = ['id', 'title', 'body', 'created'];
}

The two lists define which fields go into the response: for the list of posts and for a single post.

The result

Install the plugin through Discover and enable it. Then run:

curl http://joomla.test/api/index.php/v1/hello/posts \
  -H "X-Joomla-Token: your_token"

The response is JSON in the JSON:API format: a data array where every post has type, id and attributes with the title and the date. The address v1/hello/posts/1 returns one post together with its text.

Common mistake

An API token grants the same permissions as the account of its owner. A super user token baked into a mobile app or a script on someone else's server means full access to the site for anyone who finds it. Create a separate user with the minimum permissions needed for the exchange and keep the token like a password.

Thanks for reading!

Donate to the site — we work hard for you.