LoyalAxis CRM API — Developer Guide

A complete guide for external developers who want to connect to the LoyalAxis CRM REST API: authentication, request format, and working examples for every common operation.


What is the LoyalAxis CRM API?

The LoyalAxis CRM API is a REST API built on top of the WordPress REST API. It lets an external application — a website, a mobile app, another CRM, or an automation script — talk directly to your LoyalAxis CRM installation over HTTPS.
Typical use cases:
  • Create or update **Leads** from an external website form, landing page, or ad platform.
  • Read or update a customer's **Sales Opportunity** cards from another system.
  • Look up or create **CRM users** from a mobile app or a third-party portal.
  • Pull dashboard, kanban, or reporting data into an external BI tool.
  • Automate workflows that used to require manual work inside the CRM panel.
Every request is authenticated, JSON-based, and returns predictable HTTP status codes, so it can be consumed by any language or platform that can make an HTTPS request.

Enabling the API

> **Before you begin:** The REST API is **disabled by default**. It must be turned on by an administrator before any endpoint (other than discovery) will respond. Add the following to your site's `wp-config.php` file:
php
define( 'LA24_API_ENABLED', true );
define( 'hash_key_jwt_token', 'YOUR_CUSTOM_SECRET_KEY' );
define( 'jwt_auth_expire', 604800 ); // token lifetime in seconds, default is 7 days
ConstantRequiredDescription
`LA24_API_ENABLED`YesMust be `true` to expose the API endpoints.
`hash_key_jwt_token`YesSecret key used to sign and verify authentication tokens. Use a long, random string and keep it private.
`jwt_auth_expire`NoToken lifetime in seconds. Defaults to 7 days (`604800`) if omitted.

Base URL and Request Format

All endpoints are served under your site's standard WordPress REST API prefix:
javascript
https://yourdomain.com/wp-json/{namespace}/v{version}/{endpoint}
  • `yourdomain.com` — replace with your actual site domain.
  • `{namespace}` — identifies the module (see table below).
  • `v{version}` — the module's API version, e.g. `v1`.
  • `{endpoint}` — the specific action, e.g. `lead`, `get-kanban`.
NamespaceModuleExample
`core`Authentication (token issue/validate)`/wp-json/core/token`
`ums`Users & Leads`/wp-json/ums/v1/lead`
`sales-opportunity`Sales Opportunity (CRM pipeline)`/wp-json/sales-opportunity/v1/get-kanban`
`player`Player accounts & licenses`/wp-json/player/v1/getuser`
`knowledge`Knowledge Base`/wp-json/knowledge/v1/...`
`support`Support tickets`/wp-json/support/v1/...`
`notifications`Notifications`/wp-json/notifications/v1/...`
`warehouse`Warehouse / inventory`/wp-json/warehouse/v1/...`
`accounting`Accounting`/wp-json/accounting/v1/...`
**Request format**
  • Send `POST`, `PATCH`, and `DELETE` bodies as JSON with the header `Content-Type: application/json`. Form-encoded bodies are also accepted on most endpoints, but JSON is recommended.
  • Send `GET` parameters as a standard URL query string.
  • Every response is JSON, whatever the HTTP method or result.

Authentication

The API uses **JWT (JSON Web Token)** bearer authentication. You exchange a username and password once for a token, then send that token with every subsequent request.

Step 1 — Request a token

FieldLocationRequiredDescription
`username`BodyYesUsername of a CRM user with API access (typically an administrator).
`password`BodyYesPassword for that user.
javascript
POST /wp-json/core/token
**Example response**
json
{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
  "user_email": "admin@yourdomain.com",
  "user_nicename": "admin",
  "user_display_name": "Site Admin"
}
FieldDescription
`token`The JWT to send in the `Authorization` header on every subsequent request.
`user_email`Email address of the authenticated user.
`user_nicename`The user's WordPress "nicename" (URL-safe username).
`user_display_name`The user's display name.

Step 2 — Send the token on every request

Add this header to every authenticated request:
javascript
Authorization: Bearer {token}

Step 3 — Validate a token (optional)

javascript
POST /wp-json/core/token/validate
HeaderRequiredDescription
`Authorization`Yes`Bearer {token}` — the token to check.
A valid token returns:
json
{
  "code": "jwt_auth_valid_token",
  "data": { "status": 200 }
}

Token errors

Authentication failures use this shape (note: the error code is nested differently from normal endpoint errors — see [Request & Response Format](#request-and-response-format)):
json
{
  "code": "[jwt_auth] incorrect_password",
  "message": "The password you entered is incorrect.",
  "data": { "status": 403 }
}
Common codes: `incorrect_password`, `invalid_username` (bad login), `jwt_auth_no_auth_header` (missing `Authorization` header), `jwt_auth_bad_auth_header` (header isn't `Bearer `), `jwt_auth_invalid_token` (expired or tampered token), `jwt_auth_bad_iss` (token was issued by a different site).

Your First API Request

This walkthrough gets a real response back from the API in two calls: get a token, then fetch a lead.

Step 1 — Get a token

**cURL**
bash
curl -X POST https://yourdomain.com/wp-json/core/token \
  -d "username=your_admin_username" \
  -d "password=your_admin_password"
**JavaScript (fetch)**
javascript
const response = await fetch('https://yourdomain.com/wp-json/core/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    username: 'your_admin_username',
    password: 'your_admin_password',
  }),
});

const { token } = await response.json();
console.log(token);
**PHP**
php
$response = wp_remote_post( 'https://yourdomain.com/wp-json/core/token', array(
    'body' => array(
        'username' => 'your_admin_username',
        'password' => 'your_admin_password',
    ),
) );

$body  = json_decode( wp_remote_retrieve_body( $response ), true );
$token = $body['token'] ?? null;

Step 2 — Call an endpoint with the token

Example: retrieve a lead by ID (`GET /ums/v1/lead/:id`).
**cURL**
bash
curl -X GET https://yourdomain.com/wp-json/ums/v1/lead/123 \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
**JavaScript (fetch)**
javascript
const response = await fetch('https://yourdomain.com/wp-json/ums/v1/lead/123', {
  method: 'GET',
  headers: { 'Authorization': `Bearer ${token}` },
});

const result = await response.json();
console.log(result);
**PHP**
php
$response = wp_remote_get( 'https://yourdomain.com/wp-json/ums/v1/lead/123', array(
    'headers' => array(
        'Authorization' => 'Bearer ' . $token,
    ),
) );

$result = json_decode( wp_remote_retrieve_body( $response ), true );

Example response

json
{
  "status": 200,
  "message": "Lead retrieved successfully.",
  "data": {
    "id": 123,
    "display_name": "John Doe",
    "email": "john@example.com",
    "registered_date": "2026-05-01 10:12:00",
    "customer_type": "1",
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+989123456789",
    "phone_numbers": [
      { "tell": "+989123456789", "desc": "", "default": "1" }
    ],
    "gender": "1",
    "job": "Manager",
    "created_by": { "id": 1, "name": "Site Admin" }
  }
}

Field-by-field explanation

FieldTypeDescription
`status`NumberHTTP-style status code repeated in the body (`200` = success).
`message`StringHuman-readable summary of the result.
`data.id`NumberThe lead's unique ID.
`data.display_name`StringFull display name shown in the CRM.
`data.email`StringLead's email address.
`data.registered_date`StringWhen the lead was created (`Y-m-d H:i:s`).
`data.customer_type`String`1` = individual, `2` = company.
`data.first_name` / `data.last_name`StringName fields (individual).
`data.company_name`StringPresent only when `customer_type` is `2`.
`data.phone`StringPrimary phone number.
`data.phone_numbers`ArrayAll phone numbers on file, each with `tell`, `desc`, and `default`.
`data.gender`String`1` = male, `2` = female.
`data.job`StringJob title, if provided.
`data.created_by`ObjectThe CRM user (`id`, `name`) who created the lead.

API Reference Overview

Discovering endpoints

Every endpoint in the CRM is grouped by module (`Authentication`, `Leads`, `SalesOpportunity`, `Player`, `Knowledge Base`, `Support`, `Notifications`, `Warehouse`, `Accounting`, and more). The complete, always up-to-date list of endpoints — with every parameter and example — is published at the link in [Official API Reference](#official-api-reference). This guide covers the concepts and the most common operations; use the reference for the full endpoint catalog.

Request and response format

Almost every module endpoint returns the same envelope:
json
{
  "status": 200,
  "message": "Optional human-readable message.",
  "data": {}
}
FieldAlways presentDescription
`status`YesNumeric status code, mirrors the HTTP status.
`message`UsuallyShort description of the result, useful for logging or display.
`data`On successThe actual payload — an object, array, or list of records.
The **authentication endpoints** (`/core/token`, `/core/token/validate`) are the one exception: on failure they return a WordPress-style error object instead:
json
{
  "code": "jwt_auth_invalid_token",
  "message": "Signature verification failed.",
  "data": { "status": 403 }
}
Always check the **HTTP status code** of the response first — it is authoritative — and use `status`/`code` and `message` in the body to display or log details.

HTTP status codes

CodeMeaning
`200`Success.
`400`Bad request — a required parameter is missing or invalid.
`403`Forbidden — missing/invalid token, or the authenticated user lacks permission for this action.
`404`Not found — the record (lead, card, board, etc.) does not exist.
`500`Server error — something failed while processing the request; check `message` for detail.

Pagination

List endpoints that can return many records accept `page` and `per_page` query parameters and return a `pagination` object:
javascript
GET /wp-json/sales-opportunity/v1/get-cards?page=2&per_page=25
json
{
  "status": 200,
  "data": [ /* records for this page */ ],
  "pagination": {
    "page": 2,
    "per_page": 25,
    "total": 118,
    "total_pages": 5
  }
}
FieldDescription
`page`The page you requested (default `1`).
`per_page`Records per page (default varies by endpoint, commonly `25`).
`total`Total number of matching records across all pages.
`total_pages`Total number of pages available.
Most list endpoints accept a `s` query parameter for a free-text search (name, email, title, depending on the endpoint), plus endpoint-specific filters such as `date_from` / `date_to`, `user_id`, `tag`, or `type`. Some list endpoints also accept a `sort` parameter for ordering results (the accepted values are documented per endpoint in the full reference). Filters that aren't supported by a given endpoint are simply ignored — check the endpoint's own documentation for the exact list it accepts.

Handling errors

  1. Check the HTTP status code.
  2. If it's not `2xx`, read `message` (or `code` for auth endpoints) for the reason.
  3. For `403` on a non-auth endpoint, re-authenticate — the token may have expired — before assuming a permissions problem.
  4. For `400`, fix the request body/parameters listed in `message` and retry.

Examples

All examples assume you already have a valid token stored in a `token` variable, sent as `Authorization: Bearer {token}`.

Retrieving data

bash
curl -X GET "https://yourdomain.com/wp-json/ums/v1/lead/123" \
  -H "Authorization: Bearer your_token_here"

Searching records

bash
curl -X GET "https://yourdomain.com/wp-json/sales-opportunity/v1/search-leads?s=john&limit=10" \
  -H "Authorization: Bearer your_token_here"
json
{
  "status": 200,
  "data": [
    {
      "id": 123,
      "label": "John Doe",
      "name": "John Doe",
      "email": "john@example.com",
      "profile_url": "https://yourdomain.com/panel/profile/?id=123&clue=on",
      "type": "clue"
    }
  ]
}

Creating a record

bash
curl -X POST "https://yourdomain.com/wp-json/ums/v1/lead" \
  -H "Authorization: Bearer your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "John",
    "last_name": "Doe",
    "lead_email": "john@example.com",
    "phone": "+989123456789",
    "customer_type": "1"
  }'
json
{
  "status": 200,
  "message": "Lead created successfully.",
  "data": {
    "status": true,
    "profile_id": 124,
    "profile_link": "https://yourdomain.com/panel/profile/?id=124",
    "display_name": "John Doe"
  }
}

Updating a record

`PATCH` updates only the fields you send; every other field on the record is left untouched.
bash
curl -X PATCH "https://yourdomain.com/wp-json/ums/v1/lead/124" \
  -H "Authorization: Bearer your_token_here" \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+989350000000" }'
json
{
  "status": 200,
  "message": "Lead updated successfully.",
  "data": {
    "status": true,
    "profile_id": 124,
    "profile_link": "https://yourdomain.com/panel/profile/?id=124",
    "display_name": "John Doe"
  }
}

Deleting a record

bash
curl -X DELETE "https://yourdomain.com/wp-json/ums/v1/lead/124" \
  -H "Authorization: Bearer your_token_here"
json
{
  "status": 200,
  "message": "Lead deleted successfully.",
  "data": { "success": true, "lead_id": 124 }
}

Paginated list with filters

bash
curl -X GET "https://yourdomain.com/wp-json/sales-opportunity/v1/get-cards?so_id=1&page=1&per_page=25&s=john" \
  -H "Authorization: Bearer your_token_here"

Handling authentication failures

**Missing token**
bash
curl -X GET "https://yourdomain.com/wp-json/ums/v1/lead/123"
json
{ "status": 403, "message": "The request cannot be processed." }
**Expired or invalid token**
json
{
  "code": "jwt_auth_invalid_token",
  "message": "Expired token",
  "data": { "status": 403 }
}
When you see a `403` with a `jwt_auth_*` code, request a fresh token (see [Authentication](#authentication)) and retry the call. If the `403` comes back with a plain `status`/`message` body instead, the token is valid but the user doesn't have permission for that action — check the user's role and capabilities in the CRM instead.

Official API Reference

This guide covers the concepts you need to get started. For the complete, endpoint-by-endpoint reference — every parameter, every response field, and every module — see the official LoyalAxis CRM API documentation:
**https://yourdomain.com/apidoc/**
> Replace `yourdomain.com` with your actual site domain in every example in this guide.

Manage Cookies

Choose which cookies this website may use. You can change your choice at any time.

Always on

Required for the website to work, for example to keep you signed in, keep your shopping cart and remember this cookie choice. They cannot be switched off.

Analytics, social media connections, live chat and personalized advertising based on your online activity. These are only used if you allow them.