Skip to content

API actions

This article would be useful for those who needs to create a custom API action.

Routing

You can define a specific route to access your API action (endpoint).

Default routes are defined here: application/Espo/Resources/routes.json.

Custom routes can be defined in following places:

  • custom/Espo/Modules/{ModuleName}/Resources/routes.json
  • custom/Espo/Custom/Resources/routes.json

Example

routes.json

[
    {
        "route": "/Hello/test/:id",
        "method": "get",
        "params": {
            "controller": "MyController",
            "action": "doSomething",
            "id": ":id"
        }
    },
    {
        "route": "/HelloWorld/:name",
        "method": "post",
        "params": {
            "controller": "MyController",
            "action": "helloWorld",
            "name": ":name"
        }
    },
    {
        "route": "/TestNoAuth",
        "method": "get",
        "params": {
            "controller": "Test",
            "action": "test"
        },
        "noAuth": true
    },
    {
        "route": "/MyAction",
        "method": "get",
        "actionClassName": "Espo\\Modules\\MyModule\\Api\\MyAction"
    }
]
  • noAuth makes an endpoint not requiring authentication.
  • method specifies an HTTP method. The mostly used methods are: get, post, put, delete.
  • actionClassName defines an action class name.

A route can contain placeholds (for example, :id). An action value will be passed to an Action in the Request object.

A route can be processed either by an Action class or by a Controller.

Clearing cache is required after changes in routing files.

Action

As of v7.4.

Note

This is a preferable method for custom API actions.

A route can define an action class with the actionClassName parameter. Action classes should implement the interface Espo\Core\Api\Action.

Example:

<?php
namespace Espo\Modules\MyModule\Api;

use Espo\Core\Api\Action;
use Espo\Core\Api\Request;
use Espo\Core\Api\Response;
use Espo\Core\Api\ResponseComposer;

use Espo\Modules\MyModule\Service;

class MyAction implements Action
{
    public function __construct(private Service $service) {}

    public function process(Request $request): Response
    {
        // A route parameter value is passed in an URI, if defined in a route.
        // E.g. `/Hello/:id`.
        $id = $request->getRouteParams('id');

        $data = $this->service->get($id);

        return ResponseComposer::json($data);
    }
}

Custom controller

Alternative to an Action class. A Controller contain multiple methods for different actions.

In Custom folder

Create a file custom/Espo/Custom/Controllers/MyController.php.

<?php
namespace Espo\Custom\Controllers;

class MyController
{}

Clear cache (Administration > Clear Cache).

In Module folder

Create a file custom/Espo/Modules/MyModule/Resources/metadata/scopes/MyController.json.

{
    "module": "MyModule"
}

Create a file custom/Espo/Modules/MyModule/Controllers/MyController.php.

<?php
namespace Espo\Modules\MyModule\Controllers;

class MyController
{
    // Dependencies are passed to the constructor.
}

Clear cache after creating a new controller (Administration > Clear Cache).

Example:

<?php
namespace Espo\Modules\MyModule\Controllers;

use Espo\Core\Api\Request;
use Espo\Core\Api\Response;
use SomeDependency;
use stdClass;

class MyController
{
    public function __construct(private SomeDependency $someDependency)
    {}

    // Naming convention: `{method}Action{Action}`.
    public function putActionUpdate(Request $request, Response $response): stdClass
    {
        $id = $request->getRouteParam('id');
        $data = $request->getParsedBody();

        $result = $this->someDependency->doSomething($id, $data);

        // Response can be returned or written with `Response::writeBody`.
        return $result->toStdClass();
    }
}

Extending existing controller

Example for the Account scope.

Create a file (or modify if it already exists) custom/Espo/Custom/Controllers/Account.php.

<?php
namespace Espo\Custom\Controllers;

use Espo\Core\Api\Request;
use Espo\Core\Api\Response;

class Account extends \Espo\Modules\Crm\Controllers\Account
{
    /**
     *  POST api/v1/Account/action/test
     */
    public function postActionTest(Request $request, Response $response): bool
    {
        $someParam = $request->getQueryParam('someParam'); // GET parameter        
        $data = $request->getParsedBody(); // payload

        $someValue = $data->someKey ?? null;

        $response->setStatus(201); // example how to set custom response status code

        // call some service class here

        return $someData; // can be true, false, array or object.
    }

    /**
     *  GET api/v1/Account/action/test
     */
    public function getActionTest(Request $request, Response $response): void
    {
        $someParam = $request->getQueryParam('someParam'); // GET parameter

        // call some service class here

        $response->writeBody('true');
    }
}

Note

For the Account entity type we extend Espo\Modules\Crm\Controllers\Account. Some entity types might not have controllers in Espo\Modules\Crm\Controllers namespace. They are defined in Espo\Controllers namespace.

CRUD actions

<?php
namespace Espo\Custom\Controllers;

use Espo\Core\Api\Request;
use Espo\Core\Api\Response;

class MyController
{   
    // Creates a record.
    public function postActionCreate(Request $request, Response $response): void
    {}

    // Reads a record.
    public function getActionRead(Request $request, Response $response): void
    {}

    // Updates a record.
    public function putActionUpdate(Request $request, Response $response): void
    {}

    // Deletes a record.
    public function deleteActionDelete(Request $request, Response $response): void
    {}
}