PVR
GitHub
Dev data api

Data & API Integration

How the kit talks to a backend through API_CONFIG, what the bundled mock API provides, and how to point the kit at your own server.

4 min read
Updated June 20, 2026

The kit's list pages and forms fetch their data over AJAX. Every endpoint URL is built from a single configuration object — API_CONFIG, defined in assets/js/core/app.js — so you point the whole kit at your backend in one place. A reference mock API is bundled so the pages work out of the box while you build the real server.

API_CONFIG — the endpoint map

API_CONFIG lives in the API CONFIG section of app.js. It centralizes the base URL, a named map of endpoint paths grouped by feature, the default headers, and a getUrl() helper:

const API_CONFIG = {
    baseUrl: window.location.hostname === 'localhost'
        ? 'http://localhost:8080/taxi-crm/api'
        : 'https://api.pvrtechstudio.com/taxi-crm/api',
 
    endpoints: {
        RoleMaster:  { getRoleMaster:  '/RoleMaster/getRoleMaster' },
        Driver:      { getDriver:       '/Driver/getDriver' },
        BookingReport: { getBookingReport: '/BookingReport/getBookingReport' },
        // …one group per feature…
    },
 
    headers: { 'x_pvr_tech_studio_access': '123' },
 
    getUrl: function (endpoint) {
        return this.baseUrl + endpoint;   // baseUrl + path → full URL
    }
};
MemberWhat it is
API_CONFIG.baseUrlYour server's base URL. Set this to point the kit at your API.
API_CONFIG.endpointsNamed endpoint paths grouped by feature, e.g. RoleMaster.getRoleMaster.
API_CONFIG.headersDefault request headers sent with each call.
API_CONFIG.getUrl(path)Joins baseUrl + an endpoint path into a full URL.

A page never hard-codes a URL — it reads it from this map:

API_CONFIG.getUrl(API_CONFIG.endpoints.RoleMaster.getRoleMaster)
// → "http://localhost:8080/taxi-crm/api/RoleMaster/getRoleMaster"

How a list page fetches data

DataTables list pages pass that URL straight into the table's ajax option. This is the real roleMaster.js page script (trimmed):

self.table = $('#initDataTable').DataTable({
    dom: app.datatables.getDom(),
    processing: true,
    ajax: {
        url: API_CONFIG.getUrl(API_CONFIG.endpoints.RoleMaster.getRoleMaster),
        dataSrc: "data"            // read rows from the response's `data` array
    },
    columns: self.getColumns(),    // map each column to a field, e.g. { data: "role" }
    initComplete: function (settings, json) {
        app.datatables.initToolbar(this.api(), self.table, {
            addButton: { text: 'Add Role', href: 'addRoleMaster.html' }
        });
    }
});

The key contract: dataSrc: "data" tells DataTables the rows live under the response's data property, and each column's data key (role, description, status, …) names a field on each row object. The full DataTable recipe is in Tables and the helpers (getDom, initToolbar, renderers) in JavaScript Helpers.

Forms post the same way — build the URL with API_CONFIG.getUrl(...) and fetch() it:

fetch(API_CONFIG.getUrl(API_CONFIG.endpoints.MailSettings.saveMailSettings), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', ...API_CONFIG.headers },
    body: JSON.stringify(payload)
})
.then(r => r.json())
.then(res => { /* res.status, res.code, res.message, res.data */ });

The bundled mock API

The kit ships with a small Express reference backend (the services/api package in the distribution) so the demo pages have data to load. It is a reference implementation — you can run it as-is during development, or read it to learn the exact response shape your real backend must return, then replace it.

Each feature is a folder with a route and a controller that returns a static JSON fixture. The controller wraps every fixture in the same envelope. For RoleMaster:

// routes mount each feature under /taxi-crm/api/<Feature>
app.use("/taxi-crm/api/RoleMaster", routes.RoleMaster);
 
// RoleMaster.routes.js maps the verb + path to the controller
const routeDefinitions = {
    "/getRoleMaster": { get: [ RoleMaster.getRoleMaster ] }
};
 
// RoleMaster.controller.js returns the fixture in the standard envelope
exports.getRoleMaster = async (req, res) => {
    res.status(200).json({
        status:  'success',
        code:    5002,                      // dataRetrievedCode
        message: 'Data fetched successfully',
        data:    roleMasterData.data        // the array DataTables reads via dataSrc:"data"
    });
};

So the live request and response for the Role Master page look like this:

GET http://localhost:8080/taxi-crm/api/RoleMaster/getRoleMaster
Headers: x_pvr_tech_studio_access: 123
{
  "status": "success",
  "code": 5002,
  "message": "Data fetched successfully",
  "data": [
    { "role": "Administrator", "description": "Full access", "status": "Active", "totalUsers": 4 },
    { "role": "Dispatcher",    "description": "Bookings & dispatch", "status": "Active", "totalUsers": 12 }
  ]
}

The response envelope

Every endpoint returns the same four-field envelope. Your backend should match it so the page scripts keep working unchanged:

FieldMeaning
status"success" or an error status.
codeA numeric application code (e.g. 5002 = data retrieved, 5008 = failure).
messageHuman-readable message.
dataThe payload — for list pages, the array DataTables reads via dataSrc: "data".

Recipe: point the kit at your own backend

  1. Set the base URL. In API_CONFIG (the API CONFIG section of app.js), change baseUrl to your server, e.g. https://api.yourcompany.com/taxi-crm/api. The included logic already switches between a localhost URL and a production URL — adjust both to suit.
  2. Match the paths. Keep the existing /{Feature}/{action} paths if you can — then nothing else changes. If your routes differ, edit the values in API_CONFIG.endpoints to match your server's paths.
  3. Return the envelope. Make each endpoint respond with the &#123; status, code, message, data &#125; shape above, with the row array under data. Match the field names each page's columns expect (e.g. role, status, totalUsers for Role Master) — read the page script's columns/getColumns() to see the field names, or the matching mock controller's JSON fixture.
  4. Set headers / auth. Put any required headers (API key, bearer token) in API_CONFIG.headers; they are sent with the AJAX calls.
  5. Add new endpoints by adding an entry to API_CONFIG.endpoints and referencing it with API_CONFIG.getUrl(API_CONFIG.endpoints.<Feature>.<name>).

The kit and mock API share the path layout: API_CONFIG.endpoints.RoleMaster.getRoleMaster = /RoleMaster/getRoleMaster, which the Express app mounts at /taxi-crm/api/RoleMaster/getRoleMaster. Keep them aligned and pages need no further edits.

Note: translations are fetched too

Separately from API_CONFIG, the i18n engine loads locale JSON with fetch() from assets/locales/. Some browsers block fetch() on file:// URLs, so if text shows raw keys instead of translations, serve the folder over HTTP. Details in Internationalization.

Was this page helpful?