Trongate Docs
switch to dark modeswitch to dark mode
Custom API Endpoints

Custom API Endpoints

Throughout this chapter, everything we've been doing has involved using Trongate's built-in API endpoints - all of which invoke code that's inside Api.php, which is inside the engine folder.  Even with before hooks, after hooks and authorization rules in place, we're still ultimately falling back upon endpoints that have been pre-built into the framework.

However, there may be situations when you'd like to build your own API endpoints.  That is, API endpoints that do not call upon or use any of Trongate's built-in endpoints.

The Most Basic Custom Endpoint That's Possible

Strictly speaking, an API endpoint is just a URL that has been designed to issue responses to HTTP requests.  So, the PHP code below could produce an acceptable and perfectly valid API endpoint:

function hello() {
    echo 'hello';

Even without declaring the hello() method on an api.json file and even without actively declaring an HTTP response status code, the method above would still behave like a valid endpoint.  In fact, PHP would automatically issue an HTTP response status code of 200 for us, whenever a method like hello() is invoked.

Therefore, to be clear, we do not need to declare any of our custom endpoints inside any api.json file.   We can simply write our own methods and forget about everything covered in this chapter!  However, declaring a method - like the one shown above - inside an api.json file has two benefits:   

  • We can test our method inside the Trongate API Explorer
  • We can easily apply advanced authorization rules to our endpoint

Declaring A Custom Endpoint

The process for declaring a custom API endpoint, within an api.json file, is fundamentally the same as before.  The only key difference is the 'url_segments' property.  For custom API endpoints, the first URL segment (as defined by 'url_segments') should represent the module to be loaded and the second segment should represent the method to be invoked.

For example, suppose you had a method called hello(), inside a 'members' module.  Such a method could be declared inside an api.json file with the following syntax:

  "Hello": {
    "url_segments": "members/hello",
    "request_type": "GET",
    "description": "Say hello",
    "authorization": "*"

Applying Security Rules

Trongate's token based API authorization system can be applied to a custom endpoint by adding the following line of code onto the start of a given method:


Let's Test This!

Let's create a method inside a controller file called hello().  We'll use precisely the same code as above, only this time, we'll add API authorization.  This gives us:

​function hello() {
    echo 'hello';

Just To Let You Know
For this demonstration, we'll assume that our hello() method is inside a 'members' module.  However, it could be inside any valid Trongate module.

Now, if you open your browser and navigate to your custom endpoint, you'll find that API authorization is now being enforced.  As a matter of fact, if you don't have authorization rules declared - for your custom endpoint - then you'll see a warning on your screen, telling you why the endpoint has not been activated!

endpoint not activated alert

Did You Know?
When a custom API endpoint, like the one described, above is accessed, Trongate will attempt to read a security token from the header of the inbound HTTP request.  However, if a valid Trongate security token is not found, in the header, then Trongate will revert to checking cookies and session data for a valid token.

The normal mechanisms for declaring before hooks and after hooks (on an api.json file) will not work for custom API endpoints.  In instances where you'd like your custom endpoint to invoke other methods, just use ordinary PHP code.

Practical Example

Let's assume that we have an app that contains a module named 'members'.  On our Members.php controller file, we could have a method that loads information relating to the members' account records.  In a real-world situation, this kind of information might be private and we may wish to refuse access to everyone except:

  • users who have a role of 'admin'
  • users who can be matched with the particular record being queried

To make this as simple as possible, let's start with a basic PHP method that attempts to read a hypothetical 'member code' from a URL and then fetch a record, from the database, where a record is found to match our code:

function account($member_code) {
    $member_obj = $this->model->get_one_where('code', $member_code, 'members');

    if ($member_obj == false) {
        http_response_status(400); //bad request!
        echo 'Invalid member code';
    } else {
        echo json_encode($member_obj);


As things stand, our method above would successfully fetch a record and return a JSON object, provided all required table columns and correlating data were in place.  However, this API endpoint would be wide open!  So, anyone who happened to have a valid 'member code' could access private information relating to member accounts.

To solve this, we could combine Role Based Authorization with User Owned Segment Authorization.  Our goals here would be:

  • to use Role Based Authorization to check if the end user has a role of 'admin'
  • to use User Owned Segment authorization to check if the record being fetched belongs to the end user.

Just To Let You Know
With Trongate, end users only have to pass one API authorization test to be granted access to a secure API endpoint.

Our two required authorization tests could be applied to an API endpoint setting with the following code:

"authorization": {
    "roles": ["admin"],
    "userOwnedSegment": {
        "column": code,
        "segmentNum": 3

Just To Let You Know
For this example to be meaningful, we have to assume that we have a 'members' database table that has a column called 'code' and another column called 'trongate_user_id'.


To add API Authorization to our custom endpoint, we have to add 'api_auth()' onto the start of our account() method.  This leaves us with a method that has the following PHP code:

​function account($member_code) {
​    $member_obj = $this->model->get_one_where('code', $member_code, 'members');

​    if ($member_obj == false) {
​        http_response_status(400); //bad request!
​        echo 'Invalid member code';
​        die();
​    } else {
​        http_response_code(200);
​        echo json_encode($member_obj);
​    }



The code for declaring our custom API endpoint setting could take the following form:

"Fetch Account": {
​    "url_segments": "members/account",
​    "request_type": "GET",
​    "description": "Fetch account information",​
    "authorization": {
​        "roles": ["admin"],
​        "userOwnedSegment": {
            "column": code,
​            "segmentNum": 3
​        }


If you have a question or a comment relating to anything you've see here, please goto the Help Bar.