Joomla 4 introduced a powerful, built-in Web Services API that transforms the CMS into a fully capable headless platform. If you are migrating a custom extension from Joomla 3 to Joomla 4, or if you are building a modern mobile application that needs to interact with your site's data, mastering the Joomla 4 Web Services API is essential. This guide will walk you through the architecture, the routing system, and how to implement custom endpoints for your extensions.
By the end of this tutorial, you will understand how to register routes, handle requests in a dedicated API controller, and ensure your data is returned in a clean, standardized JSON format. Whether you want to follow the strict "Joomla Way" or need a more flexible, granular approach, we have you covered.
Understanding the Joomla 4 Web Services Architecture
Unlike previous versions where developers had to rely on third-party extensions to create RESTful interfaces, Joomla 4 provides a native API framework located in the /api directory. This is a separate application entry point from the site or administrator applications.
When you make a request to yoursite.com/api/v1/something, Joomla initializes the ApiApplication. This application looks for plugins in the webservices group to define available routes. To make your component accessible via the API, you must create a web services plugin and define your controllers and views within the component's src directory specifically for the API.
The File Structure You Need
To bring a single REST endpoint online for a custom component (e.g., com_timetracker), you typically need to interact with four specific locations:
- Plugin:
[root]/plugins/webservices/timetracker/timetracker.php(Registers the routes) - API Controller:
[root]/api/components/com_timetracker/src/Controller/ClientsController.php(Handles the logic) - API View:
[root]/api/components/com_timetracker/src/View/Clients/JsonapiView.php(Defines the output fields) - Admin Model:
[root]/administrator/components/com_timetracker/src/Model/ClientsModel.php(Fetches the data)
Setting Up Your Web Services Plugin
The web services plugin is the gatekeeper of your API. It listens for the onBeforeApiRoute event to register your component's endpoints. Here is how you can implement a standard CRUD (Create, Read, Update, Delete) route mapping.
<?php
// [root]/plugins/webservices/timetracker/timetracker.php
defined('_JEXEC') or die;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Router\ApiRouter;
class PlgWebservicesTimetracker extends CMSPlugin
{
protected $autoloadLanguage = true;
public function onBeforeApiRoute(&$router)
{
$router->createCRUDRoutes(
'v1/timetracker',
'clients',
['component' => 'com_timetracker']
);
}
}
In this example, createCRUDRoutes automatically generates five routes for you:
- GET v1/timetracker/clients (List items)
- GET v1/timetracker/clients/:id (Get single item)
- POST v1/timetracker/clients (Create item)
- PATCH v1/timetracker/clients/:id (Update item)
- DELETE v1/timetracker/clients/:id (Delete item)
Implementing the API Controller and View
Once the route is registered, Joomla looks for a controller. In the API context, your controller should extend ApiController. This base class handles much of the heavy lifting, including interacting with your component's model and rendering the JSON response.
The API Controller
<?php
namespace Joomla\Component\Timetracker\Api\Controller;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\Controller\ApiController;
class ClientsController extends ApiController
{
protected $contentType = 'clients';
protected $default_view = 'clients';
}
The API View
Joomla 4 uses the JSON:API specification. You must define which fields from your model should be exposed to the API in a JsonapiView.php file.
<?php
namespace Joomla\Component\Timetracker\Api\View\Clients;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\View\JsonApiView as BaseApiView;
class JsonapiView extends BaseApiView
{
protected $fieldsToRenderItem = [
'id',
'business_name',
'notes',
];
protected $fieldsToRenderList = [
'id',
'business_name',
];
}
Important Note: Joomla 4's API router uses singularization logic. If your $contentType is clients, the ApiController will attempt to load a model named ClientModel (singular) from the administrator section of your component. Ensure your model naming conventions follow this rule to avoid RouteNotFoundException or class loading errors.
Advanced: Creating Custom Granular Routes
Sometimes, standard CRUD routes aren't enough. You might need a specific endpoint for a specialized task, such as fetching records for a specific technician. Instead of using createCRUDRoutes, you can define granular routes using the Route class.
use Joomla\Router\Route;
public function onBeforeApiRoute(&$router)
{
$defaults = ['component' => 'com_timetracker', 'public' => false];
$routes = [
new Route(['GET'], 'v1/timetracker/records/technician/:id', 'records.getTechnicianRecords', ['id' => '(\\d+)'], $defaults),
];
$router->addRoutes($routes);
}
In your RecordsController.php, you would then implement the getTechnicianRecords method:
public function getTechnicianRecords()
{
$technicianId = $this->input->getInt('id', 0);
if ($technicianId > 0) {
$this->modelState->set('filter.technician_id', $technicianId);
}
return parent::displayList();
}
This approach gives you full control over the URL structure and the logic executed, without being forced into the standard CRUD pattern.
Frequently Asked Questions
Why am I getting a "RouteNotFoundException"?
This error usually occurs for one of three reasons: your web services plugin is not published, the component name in the route defaults is incorrect (e.g., missing the com_ prefix), or your controller/view file structure does not match the namespace declared in the router. Double-check that your plugin is active in the Plugin Manager.
Can I use the API without authentication?
By default, Joomla 4 API routes require a valid API Token (found in the User Profile). However, you can make a route public by setting 'public' => true in the $defaults array of your route definition. Use this with caution to avoid exposing sensitive data.
Does the API use the Site or Administrator models?
The Joomla 4 API application specifically looks for models in the administrator/components/com_yourcomponent/src/Model directory. It uses the AdminModel class hierarchy to ensure that data validation and access rules defined for the backend are respected.
Wrapping Up
The Joomla 4 Web Services API is a robust tool that brings Joomla into the modern era of decoupled web development. While the "Joomla Way" of using createCRUDRoutes offers a standardized approach that minimizes code duplication, the granular routing system provides the flexibility needed for complex applications.
When developing your API integration, remember to keep your models in the administrator directory and pay close attention to singular/plural naming conventions. With these patterns in place, you can easily bridge the gap between your Joomla database and any external application, from Android apps to React frontends.