-
-
-
- v2.0 Developer API
-
-
-
- NearleDaily API
-
-
-
- A comprehensive, lightning-fast platform designed for logistics, order management, and multi-tenant POS administration.
-
-
-
- {topics.map((topic, index) => {
- const Icon = topicIcons[topic.id] || Zap;
- return (
-
setActiveTopic(topic)}
- className="group relative bg-white p-6 rounded-2xl border border-slate-200/60 shadow-sm hover:shadow-xl hover:shadow-brand-500/5 hover:border-brand-200 transition-all duration-300 cursor-pointer overflow-hidden"
- style={{ animationDelay: `${index * 100}ms` }}
- >
-
-
-
-
-
-
-
- {topic.name}
-
-
-
- {topic.description}
-
-
-
- )})}
-
-
-
-
-
- Explore real-time interactive endpoints. All requests are authenticated with secure admin secrets internally for demonstration purposes.
-
-
-
+
+
)}
diff --git a/src/components/EndpointViewer.jsx b/src/components/EndpointViewer.jsx
index de90107..b0b2706 100644
--- a/src/components/EndpointViewer.jsx
+++ b/src/components/EndpointViewer.jsx
@@ -1,86 +1,120 @@
import React, { useState, useEffect } from 'react';
-import { Play, FileJson, Server, CheckCircle2, AlertCircle } from 'lucide-react';
+import { Play, FileJson, Server, CheckCircle2, AlertCircle, Copy, Check, Loader2 } from 'lucide-react';
import { graphqlMeta } from '../data/apiData';
+import { highlightJSON } from '../lib/highlight';
+
+function safeDecode(v) {
+ try { return decodeURIComponent(v); } catch { return v; }
+}
+
+function parseUrlParams(url) {
+ const [, query = ''] = url.split('?');
+ const params = {};
+ if (query) {
+ for (const pair of query.split('&')) {
+ const [name, value = ''] = pair.split('=');
+ if (name) params[name] = safeDecode(value);
+ }
+ }
+ return params;
+}
+
+function EndpointRow({ endpoint, topic }) {
+ const isRest = topic.type === 'rest';
+ const meta = !isRest ? graphqlMeta[endpoint.name] : null;
-function EndpointRow({ endpoint }) {
- const meta = graphqlMeta[endpoint.name];
const [queryText, setQueryText] = useState(meta?.query || '');
const [variablesText, setVariablesText] = useState(meta?.variables || '{}');
-
- const parseParams = (url) => {
- const parts = url.split('?');
- if(parts.length < 2) return {};
- const sp = new URLSearchParams(parts[1]);
- const obj = {};
- for(const [k, v] of sp.entries()) obj[k] = v;
- return obj;
- };
-
- const [params, setParams] = useState(parseParams(endpoint.url));
+ const [params, setParams] = useState(() => parseUrlParams(endpoint.url));
const [result, setResult] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
+ const [copied, setCopied] = useState(false);
useEffect(() => {
setQueryText(meta?.query || '');
setVariablesText(meta?.variables || '{}');
- }, [meta?.query, meta?.variables]);
-
- useEffect(() => {
- setParams(parseParams(endpoint.url));
- }, [endpoint.url]);
-
- useEffect(() => {
- try {
- const parsed = variablesText?.trim() ? JSON.parse(variablesText) : {};
- if(endpoint.method === 'GET') {
- const next = {};
- Object.keys(params).forEach(k => {
- next[k] = parsed[k] !== undefined ? String(parsed[k]) : params[k];
- });
- setParams(next);
- }
- } catch(e) {}
+ setParams(parseUrlParams(endpoint.url));
+ setResult(null);
+ setError(null);
}, [endpoint.name]);
+ const copyResponse = async () => {
+ if (!result) return;
+ try {
+ await navigator.clipboard.writeText(JSON.stringify(result.data, null, 2));
+ setCopied(true); setTimeout(() => setCopied(false), 1500);
+ } catch {}
+ };
+
const execute = async () => {
setError(null);
setIsLoading(true);
setResult(null);
try {
- const base = 'https://api.workolik.com';
- let requestUrl = base + endpoint.url;
- const options = {
- method: endpoint.method,
- headers: {
- 'x-hasura-admin-secret': 'nearle-admin-secret',
- 'Content-Type': 'application/json'
- }
- };
-
- if (endpoint.method === 'GET' && !endpoint.useGraphql) {
- const emptyKeys = Object.entries(params).filter(([k,v]) => String(v).trim() === '').map(([k])=>k);
- if (emptyKeys.length) {
- setError('Required parameter(s): ' + emptyKeys.join(', '));
- setIsLoading(false);
- return;
- }
+ if (isRest) {
+ // REST: fetch directly (fiesta.nearle.app supports CORS)
const path = endpoint.url.split('?')[0];
- const qs = new URLSearchParams(params).toString();
- requestUrl = base + path + (qs ? '?' + qs : '');
- } else {
- const parsedVariables = variablesText?.trim() ? JSON.parse(variablesText) : {};
- requestUrl = base + '/v1/graphql';
- options.method = 'POST';
- options.body = JSON.stringify({ query: queryText, variables: parsedVariables });
- }
+ const isGet = endpoint.method === 'GET';
+ let url = topic.baseUrl + endpoint.url;
- const res = await fetch(requestUrl, options);
- const data = await res.json();
-
- setResult({ status: res.status, ok: res.ok, data });
- } catch(err) {
+ if (isGet && Object.keys(params).length > 0) {
+ const qs = new URLSearchParams(params).toString();
+ url = topic.baseUrl + path + (qs ? '?' + qs : '');
+ }
+
+ const options = {
+ method: endpoint.method,
+ headers: { 'Content-Type': 'application/json' },
+ };
+
+ if (!isGet && endpoint.body) {
+ options.body = typeof endpoint.body === 'string'
+ ? endpoint.body
+ : JSON.stringify(endpoint.body);
+ }
+
+ const res = await fetch(url, options);
+ const text = await res.text();
+ let data;
+ try { data = JSON.parse(text); } catch { data = text; }
+ setResult({ status: res.status, ok: res.ok, data });
+
+ } else {
+ // GraphQL / Hasura
+ const base = topic.baseUrl;
+ let requestUrl = base + endpoint.url;
+ const options = {
+ method: endpoint.method,
+ headers: {
+ 'x-hasura-admin-secret': 'nearle-admin-secret',
+ 'Content-Type': 'application/json',
+ },
+ };
+
+ if (endpoint.method === 'GET' && !endpoint.useGraphql) {
+ const emptyKeys = Object.entries(params).filter(([, v]) => String(v).trim() === '').map(([k]) => k);
+ if (emptyKeys.length) {
+ setError('Required parameter(s): ' + emptyKeys.join(', '));
+ setIsLoading(false);
+ return;
+ }
+ const path = endpoint.url.split('?')[0];
+ const qs = new URLSearchParams(params).toString();
+ requestUrl = base + path + (qs ? '?' + qs : '');
+ } else {
+ const parsedVars = variablesText?.trim() ? JSON.parse(variablesText) : {};
+ requestUrl = base + '/v1/graphql';
+ options.method = 'POST';
+ options.body = JSON.stringify({ query: queryText, variables: parsedVars });
+ }
+
+ const res = await fetch(requestUrl, options);
+ const data = await res.json();
+ setResult({ status: res.status, ok: res.ok, data });
+ }
+ } catch (err) {
setError(String(err));
} finally {
setIsLoading(false);
@@ -88,16 +122,19 @@ function EndpointRow({ endpoint }) {
};
const methodColor = {
- GET: 'bg-emerald-100/50 text-emerald-700 border-emerald-200',
- POST: 'bg-blue-100/50 text-blue-700 border-blue-200',
- PUT: 'bg-amber-100/50 text-amber-700 border-amber-200',
- DELETE: 'bg-red-100/50 text-red-700 border-red-200'
+ GET: 'bg-emerald-100/50 text-emerald-700 border-emerald-200',
+ POST: 'bg-blue-100/50 text-blue-700 border-blue-200',
+ PUT: 'bg-amber-100/50 text-amber-700 border-amber-200',
+ DELETE: 'bg-red-100/50 text-red-700 border-red-200',
+ PATCH: 'bg-purple-100/50 text-purple-700 border-purple-200',
}[endpoint.method] || 'bg-slate-100/50 text-slate-700 border-slate-200';
+ const urlPath = endpoint.url.split('?')[0];
+
return (
-
+
{/* Left Column: Description & Parameters */}
@@ -114,10 +151,11 @@ function EndpointRow({ endpoint }) {
- https://api.workolik.com
- {endpoint.url.split('?')[0]}
+ {topic.baseUrl}
+ {urlPath}
+ {/* Query params (GET endpoints) */}
{endpoint.method === 'GET' && Object.keys(params).length > 0 && (
@@ -130,22 +168,21 @@ function EndpointRow({ endpoint }) {
{key}
string
- {
const newVal = e.target.value;
- setParams(p => {
- const next = {...p, [key]: newVal};
+ setParams(p => ({ ...p, [key]: newVal }));
+ if (!isRest) {
try {
setVariablesText(JSON.stringify({
...JSON.parse(variablesText || '{}'),
[key]: isNaN(newVal) || newVal === '' ? newVal : Number(newVal)
}, null, 2));
- } catch(err) {}
- return next;
- });
+ } catch {}
+ }
}}
/>
@@ -155,10 +192,10 @@ function EndpointRow({ endpoint }) {
)}
- {/* Right Column: Execution & Code */}
+ {/* Right Column: Code Panel */}
-
+
{/* macOS window dots */}
@@ -167,23 +204,24 @@ function EndpointRow({ endpoint }) {
Request Payload
+ {/* Pane content */}
{meta ? (
+ // GraphQL editor: query + variables
+ ) : endpoint.body ? (
+ // REST body JSON preview
+
+
+ Request Body (JSON)
+
+
+
) : (
-
-
-
-
No specific payload configuration required.
+ // URL preview for no-body endpoints
+
+
+ Full Request URL
+
+
+ {endpoint.method}
+ {topic.baseUrl}
+ {urlPath}
+ {Object.keys(params).length > 0 && (
+ <>
+ ?
+ {Object.entries(params).map(([k, v], i, arr) => (
+
+ {k}
+ =
+ {encodeURIComponent(v)}
+ {i < arr.length - 1 && & }
+
+ ))}
+ >
+ )}
)}
@@ -205,16 +276,14 @@ function EndpointRow({ endpoint }) {
Ready
-
- {isLoading ? (
-
- ) : (
-
- )}
+ {isLoading
+ ?
+ : }
{isLoading ? 'Executing...' : 'Send Request'}
@@ -224,25 +293,39 @@ function EndpointRow({ endpoint }) {
Response JSON
- {result && (
-
- {result.ok ? : }
- {result.status}
-
- )}
+
+ {result && (
+ <>
+
+ {result.ok ? : }
+ {result.status}
+
+
+ {copied ? : }
+ {copied ? 'Copied' : 'Copy'}
+
+ >
+ )}
+
{error ? (
{error}
+ ) : typeof result?.data === 'string' ? (
+
{result.data}
) : (
-
- {JSON.stringify(result.data, null, 2)}
-
+
)}
)}
-
+
);
@@ -256,11 +339,22 @@ export default function EndpointViewer({ topic }) {
{topic.name}
{topic.description}
+
+
+
+ {topic.type === 'graphql' ? 'GraphQL' : 'REST API'}
+
+ {topic.endpoints.length} endpoint{topic.endpoints.length !== 1 ? 's' : ''}
+
{topic.endpoints.map(endpoint => (
-
+
))}
diff --git a/src/components/Introduction.jsx b/src/components/Introduction.jsx
new file mode 100644
index 0000000..e4eca27
--- /dev/null
+++ b/src/components/Introduction.jsx
@@ -0,0 +1,103 @@
+import React from 'react';
+import { ArrowRight, Code2, Zap, Users, ShoppingCart, Home, Box, Link2, Truck, UserCircle, Bike, FileText, CreditCard, Wrench } from 'lucide-react';
+import { GRAPHQL_BASE_URL } from '../data/apiData';
+import { REST_BASE_URL } from '../data/restTopics';
+
+const topicIcons = {
+ users: Users,
+ orders: ShoppingCart,
+ tenants: Home,
+ products: Box,
+ locations: Link2,
+ partners: Bike,
+ deliveries: Truck,
+ customers: UserCircle,
+ invoice: FileText,
+ payments: CreditCard,
+ utils: Wrench,
+ mobile: Box,
+};
+
+export default function Introduction({ allGraphql, allRest, setActiveTopic }) {
+ const allTopics = [...allGraphql, ...allRest];
+
+ return (
+
+
+
+
+ v2.0 Developer API
+
+
+
+ NearleDaily API
+
+
+
+ A comprehensive, lightning-fast platform designed for logistics, order management,
+ and multi-tenant POS administration — available through both Hasura GraphQL and REST APIs.
+
+
+
+
Base URLs
+
+
+
Hasura GraphQL
+
{GRAPHQL_BASE_URL}
+
+
+
REST API
+
{REST_BASE_URL}
+
+
+
+
+
+ {allTopics.map((topic, index) => {
+ const Icon = topicIcons[topic.id] || Zap;
+ return (
+
setActiveTopic(topic)}
+ className="group relative bg-white p-6 rounded-2xl border border-slate-200/60 shadow-sm hover:shadow-xl hover:shadow-brand-500/5 hover:border-brand-200 transition-all duration-300 cursor-pointer overflow-hidden"
+ style={{ animationDelay: `${index * 80}ms` }}
+ >
+
+
+
+
+
+
+
+ {topic.name}
+
+
+
+
+ {topic.type === 'graphql' ? 'GraphQL' : 'REST'}
+
+ {topic.endpoints.length} endpoint{topic.endpoints.length !== 1 ? 's' : ''}
+
+
+ {topic.description}
+
+
+
+ );
+ })}
+
+
+
+
+
+ Explore real-time interactive endpoints. GraphQL requests are authenticated with the admin secret. REST endpoints support CORS and can be called directly from the browser.
+
+
+
+
+ );
+}
diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx
index 5813817..38f840f 100644
--- a/src/components/Sidebar.jsx
+++ b/src/components/Sidebar.jsx
@@ -1,23 +1,60 @@
import React, { useState } from 'react';
-import { Search, ChevronRight, ChevronDown, Layers, Terminal, Users, ShoppingCart, Home, Box, Link2 } from 'lucide-react';
+import { Search, ChevronRight, ChevronDown, Layers, Terminal, Users, ShoppingCart, Home, Box, Link2, Truck, UserCircle, Bike, FileText, CreditCard, Wrench } from 'lucide-react';
const topicIcons = {
- users: Users,
- orders: ShoppingCart,
- tenants: Home,
- products: Box,
- locations: Link2,
- partners: Users,
+ users: Users,
+ orders: ShoppingCart,
+ tenants: Home,
+ products: Box,
+ locations: Link2,
+ partners: Bike,
+ deliveries: Truck,
+ customers: UserCircle,
+ invoice: FileText,
+ payments: CreditCard,
+ utils: Wrench,
+ mobile: Box,
};
-export default function Sidebar({ topics, activeTopic, setActiveTopic, searchQuery, setSearchQuery }) {
- const [expanded, setExpanded] = useState({ general: true, topics: true });
+export default function Sidebar({ graphqlTopics, restTopics, activeTopic, setActiveTopic, searchQuery, setSearchQuery }) {
+ const [open, setOpen] = useState({ general: true, graphql: true, rest: true });
+ const toggle = (key) => setOpen(prev => ({ ...prev, [key]: !prev[key] }));
- const toggle = (key) => setExpanded(prev => ({ ...prev, [key]: !prev[key] }));
+ const renderGroup = (topics, title, key) => (
+
+
toggle(key)}
+ className="w-full flex items-center justify-between px-2 py-1.5 text-slate-800 font-semibold text-sm hover:text-brand-600 transition-colors group"
+ >
+ {title}
+ {open[key] ? : }
+
+
+ {topics.map(topic => {
+ const isActive = activeTopic?.uniqueId === topic.uniqueId;
+ const Icon = topicIcons[topic.id] || Layers;
+ return (
+ setActiveTopic(topic)}
+ className={`w-full flex items-center gap-2.5 px-3 py-2 rounded-lg text-sm transition-all duration-200 group ${
+ isActive
+ ? 'text-brand-700 bg-brand-50 shadow-sm font-medium'
+ : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100/50'
+ }`}
+ >
+
+ {topic.name}
+
+ );
+ })}
+
+
+ );
return (
-
+
{/* Brand Header */}
-
+
-
- {/* General Section */}
+
+ {/* Getting Started */}
-
toggle('general')}
className="w-full flex items-center justify-between px-2 py-1.5 text-slate-800 font-semibold text-sm hover:text-brand-600 transition-colors group"
>
Getting Started
- {expanded.general ? : }
+ {open.general ? : }
-
+
setActiveTopic(null)}
className={`w-full flex items-center gap-2.5 px-3 py-2 rounded-lg text-sm transition-all duration-200 ${
- !activeTopic
- ? 'text-brand-700 bg-brand-50 shadow-sm font-medium'
+ !activeTopic
+ ? 'text-brand-700 bg-brand-50 shadow-sm font-medium'
: 'text-slate-600 hover:text-slate-900 hover:bg-slate-100/50'
}`}
>
-
+
Introduction
- {/* Topics Section */}
-
-
toggle('topics')}
- className="w-full flex items-center justify-between px-2 py-1.5 text-slate-800 font-semibold text-sm hover:text-brand-600 transition-colors group"
- >
- API Reference
- {expanded.topics ? : }
-
-
- {topics.map(topic => {
- const isActive = activeTopic?.id === topic.id;
- const Icon = topicIcons[topic.id] || Layers;
- return (
- setActiveTopic(topic)}
- className={`w-full flex items-center gap-2.5 px-3 py-2 rounded-lg text-sm transition-all duration-200 group ${
- isActive
- ? 'text-brand-700 bg-brand-50 shadow-sm font-medium'
- : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100/50'
- }`}
- >
-
- {topic.name}
-
- )
- })}
-
-
+ {graphqlTopics.length > 0 && renderGroup(graphqlTopics, 'GraphQL', 'graphql')}
+ {restTopics.length > 0 && renderGroup(restTopics, 'REST API', 'rest')}
diff --git a/src/data/apiData.js b/src/data/apiData.js
index 0422c23..cff9a91 100644
--- a/src/data/apiData.js
+++ b/src/data/apiData.js
@@ -826,7 +826,9 @@ export const graphqlMeta = {
};
-export const topics = [
+export const GRAPHQL_BASE_URL = 'https://api.workolik.com';
+
+export const graphqlTopics = [
{
id: "users",
name: "Users",
diff --git a/src/data/restTopics.js b/src/data/restTopics.js
new file mode 100644
index 0000000..8268b18
--- /dev/null
+++ b/src/data/restTopics.js
@@ -0,0 +1,177 @@
+export const REST_BASE_URL = 'https://fiesta.nearle.app';
+
+export const restTopics = [
+ {
+ "id": "utils",
+ "name": "Utils",
+ "description": "Shared lookup endpoints: app categories, subcategories, locations, app types, configs.",
+ "endpoints": [
+ { "name": "Fetch application categories by tag (Web)", "method": "GET", "url": "/live/api/v1/web/utils/getapptypes?tag=customer", "description": "Fetch application categories by tag (Web)" },
+ { "name": "Resolve subcategories (Web)", "method": "GET", "url": "/live/api/v1/web/utils/getsubcategories?moduleid=1&categoryid=2", "description": "Resolve subcategories (Web)" },
+ { "name": "Fetch system active geofence details (Web)", "method": "GET", "url": "/live/api/v1/web/utils/getapplocations?applocationid=1", "description": "Fetch system active geofence details (Web)" },
+ { "name": "Fetch global system categories configurations (Web)", "method": "GET", "url": "/live/api/v1/web/utils/getappcategories", "description": "Fetch global system categories configurations (Web)" },
+ { "name": "Get mobile geofence configuration details (Mobile)", "method": "GET", "url": "/live/api/v1/mob/utils/getapplocationconfig?applocationid=1", "description": "Get mobile geofence configuration details (Mobile)" },
+ { "name": "Get mobile active geofence details (Mobile)", "method": "GET", "url": "/live/api/v1/mob/utils/getapplocations?applocationid=1", "description": "Get mobile active geofence details (Mobile)" },
+ { "name": "Fetch mobile app types by tag (Mobile)", "method": "GET", "url": "/live/api/v1/mob/utils/getapptypes?tag=rider", "description": "Fetch mobile app types by tag (Mobile)" },
+ { "name": "Fetch global payment & geofence configs (Mobile)", "method": "GET", "url": "/live/api/v1/mob/utils/getappconfig?configid=1", "description": "Fetch global payment & geofence configs (Mobile)" },
+ { "name": "Get mobile category subcategories list (Mobile)", "method": "GET", "url": "/live/api/v1/mob/utils/getsubcategories?moduleid=1&categoryid=2", "description": "Get mobile category subcategories list (Mobile)" },
+ { "name": "Fetch mobile app categories configurations (Mobile)", "method": "GET", "url": "/live/api/v1/mob/utils/getappcategories", "description": "Fetch mobile app categories configurations (Mobile)" }
+ ]
+ },
+ {
+ "id": "users",
+ "name": "Users",
+ "description": "Manage users, authentication, and roles across the platform.",
+ "endpoints": [
+ { "name": "Get all users (Web)", "method": "GET", "url": "/live/api/v1/web/users/getallusers?roleid=2&tenantid=8&pageno=1&pagesize=10&keyword=john", "description": "Get all users (Web)" },
+ { "name": "Get a specific user profile by ID (Web)", "method": "GET", "url": "/live/api/v1/web/users/getusers?userid=12", "description": "Get a specific user profile by ID (Web)" },
+ { "name": "Get a specific user profile by ID (Mobile)", "method": "GET", "url": "/live/api/v1/mob/users/getusers?userid=15", "description": "Get a specific user profile by ID (Mobile)" },
+ { "name": "Operator/User orders board (Web)", "method": "GET", "url": "/live/api/v1/web/orders/user/getorders?appuserid=12&status=processing&pageno=1&pagesize=10", "description": "Operator/User orders board (Web)" },
+ { "name": "Tenant Web Panel Login", "method": "POST", "url": "/live/api/v1/web/users/tenant/weblogin", "description": "Tenant Web Panel Login", "body": { "authname": "merchant_admin_01", "password": "PasswordSecurityHash99!" } },
+ { "name": "General Application Login", "method": "POST", "url": "/live/api/v1/web/users/applogin", "description": "General Application Login", "body": { "authname": "system_operator", "password": "OperatorSafePasswordSecret", "deviceid": "device_uuid_8828b", "devicetype": "android" } },
+ { "name": "Register New Web Staff Account", "method": "POST", "url": "/live/api/v1/web/users/create", "description": "Register New Web Staff Account", "body": { "authname": "tenant_staff_steve", "firstname": "Steve", "lastname": "Rogers", "password": "SteveSecurePassword12", "email": "steve.rogers@merchant.com", "dialcode": "+61", "contactno": "412345678", "roleid": 3, "pin": 1234, "address": "100 Flinders St", "suburb": "Melbourne", "city": "Melbourne", "state": "VIC", "postcode": "3000", "tenantid": 8, "locationid": 2, "applocationid": 1, "status": "active" } },
+ { "name": "Update Web Staff User Details", "method": "PUT", "url": "/live/api/v1/web/users/update", "description": "Update Web Staff User Details", "body": { "userid": 15, "firstname": "Steve", "lastname": "Captain", "email": "steve.captain@merchant.com", "contactno": "412345678", "address": "200 Flinders St", "suburb": "Melbourne", "city": "Melbourne", "state": "VIC", "postcode": "3000", "status": "active" } },
+ { "name": "Rider/Merchant Mobile App Login", "method": "POST", "url": "/live/api/v1/mob/users/tenant/login", "description": "Rider/Merchant Mobile App Login", "body": { "authname": "rider_john_01", "password": "RiderSecretKey" } },
+ { "name": "Create Mobile Staff User", "method": "POST", "url": "/live/api/v1/mob/users/create", "description": "Create Mobile Staff User", "body": { "authname": "tenant_staff_steve", "firstname": "Steve", "lastname": "Rogers", "password": "SteveSecurePassword12", "email": "steve.rogers@merchant.com", "dialcode": "+61", "contactno": "412345678", "roleid": 3, "pin": 1234, "tenantid": 8, "locationid": 2, "applocationid": 1, "status": "active" } },
+ { "name": "Update Mobile Staff Details", "method": "PUT", "url": "/live/api/v1/mob/users/update", "description": "Update Mobile Staff Details", "body": { "userid": 15, "firstname": "Steve", "lastname": "Captain", "email": "steve.captain@merchant.com", "contactno": "412345678", "status": "active" } }
+ ]
+ },
+ {
+ "id": "partners",
+ "name": "Partners",
+ "description": "Partners, riders, shifts, locations, and log sheets.",
+ "endpoints": [
+ { "name": "Partner fleet orders board (Web)", "method": "GET", "url": "/live/api/v1/web/orders/partner/getorders?partnerid=1&status=processing&pageno=1&pagesize=10", "description": "Partner fleet orders board (Web)" },
+ { "name": "Get active riders (Web)", "method": "GET", "url": "/live/api/v1/web/partners/getriders?partnerid=1&applocationid=1&userid=12&tenantid=8", "description": "Get active riders (Web)" },
+ { "name": "Get partner profiles (Web)", "method": "GET", "url": "/live/api/v1/web/partners/getpartners?partnerid=1&applocationid=1&userid=12", "description": "Get partner profiles (Web)" },
+ { "name": "Get rider shifts (Web)", "method": "GET", "url": "/live/api/v1/web/partners/getridershifts?applocationid=1", "description": "Get rider shifts (Web)" },
+ { "name": "Get location configurations (Web)", "method": "GET", "url": "/live/api/v1/web/partners/getlocations?userid=12&configid=1", "description": "Get location configurations (Web)" },
+ { "name": "Get rider log sheet (Web)", "method": "GET", "url": "/live/api/v1/web/partners/getriderlogs?partnerid=1&applocationid=1&fromdate=2026-05-20&todate=2026-05-20", "description": "Get rider log sheet (Web)" },
+ { "name": "Get partner profiles (Mobile)", "method": "GET", "url": "/live/api/v1/mob/partners/getpartners?partnerid=1&applocationid=1&userid=12", "description": "Get partner profiles (Mobile)" },
+ { "name": "Get rider log sheet (Mobile)", "method": "GET", "url": "/live/api/v1/mob/partners/getriderlogs?partnerid=1&applocationid=1&fromdate=2026-05-20&todate=2026-05-20", "description": "Get rider log sheet (Mobile)" },
+ { "name": "Get rider operational info (Mobile)", "method": "GET", "url": "/live/api/v1/mob/partners/getriderinfo?userid=15", "description": "Get rider operational info (Mobile)" },
+ { "name": "Get active riders list (Mobile)", "method": "GET", "url": "/live/api/v1/mob/partners/getriders?partnerid=1&applocationid=1&userid=15&tenantid=8", "description": "Get active riders list (Mobile)" }
+ ]
+ },
+ {
+ "id": "tenants",
+ "name": "Tenants",
+ "description": "Tenant accounts, locations, customers, pricing, onboarding.",
+ "endpoints": [
+ { "name": "Tenant orders board (Web)", "method": "GET", "url": "/live/api/v1/web/orders/tenant/getorders?tenantid=8&locationid=2&status=processing&pageno=1&pagesize=10", "description": "Tenant orders board (Web)" },
+ { "name": "Get specific tenant store orders (Mobile)", "method": "GET", "url": "/live/api/v1/mob/orders/tenant/getorders?tenantid=8&locationid=2&pageno=1&pagesize=10", "description": "Get specific tenant store orders (Mobile)" },
+ { "name": "Search registered tenants (Web)", "method": "GET", "url": "/live/api/v1/web/tenants/search?status=Active&keyword=Fresh", "description": "Search registered tenants (Web)" },
+ { "name": "Search tenants by keyword (Web)", "method": "GET", "url": "/live/api/v1/web/tenants/searchbykeyword?keyword=daily", "description": "Search tenants by keyword (Web)" },
+ { "name": "Get all active tenants catalog (Web)", "method": "GET", "url": "/live/api/v1/web/tenants/getalltenants?applocationid=1&status=Active&pageno=1&pagesize=10", "description": "Get all active tenants catalog (Web)" },
+ { "name": "Get outlet locations assigned to a tenant (Web)", "method": "GET", "url": "/live/api/v1/web/tenants/gettenantlocations?tenantid=8", "description": "Get outlet locations assigned to a tenant (Web)" },
+ { "name": "Retrieve delivery time slots config (Mobile)", "method": "GET", "url": "/live/api/v1/mob/tenants/gettenantslot", "description": "Retrieve delivery time slots config (Mobile)" },
+ { "name": "Search tenants by keyword (Mobile)", "method": "GET", "url": "/live/api/v1/mob/tenants/searchbykeyword?keyword=grocery", "description": "Search tenants by keyword (Mobile)" },
+ { "name": "Retrieve tenants associated with a customer (Mobile)", "method": "GET", "url": "/live/api/v1/mob/tenants/getcustomertenants?customerid=4082&tenant=0", "description": "Retrieve tenants associated with a customer (Mobile)" },
+ { "name": "Get outlet locations linked to a tenant (Mobile)", "method": "GET", "url": "/live/api/v1/mob/tenants/gettenantlocations?tenantid=8", "description": "Get outlet locations linked to a tenant (Mobile)" },
+ { "name": "Get logistics pricing slabs for a tenant (Mobile)", "method": "GET", "url": "/live/api/v1/mob/tenants/gettenantpricing?tenantid=8&applocationid=1", "description": "Get logistics pricing slabs for a tenant (Mobile)" },
+ { "name": "Get staff members under a tenant store (Mobile)", "method": "GET", "url": "/live/api/v1/mob/tenants/getstaffs?tenantid=8", "description": "Get staff members under a tenant store (Mobile)" },
+ { "name": "Get tenant detailed profile info (Mobile)", "method": "GET", "url": "/live/api/v1/mob/tenants/gettenantinfo?tenantid=8&locationid=2", "description": "Get tenant detailed profile info (Mobile)" },
+ { "name": "Link Customer Profile to Tenant Store", "method": "POST", "url": "/live/api/v1/web/tenants/createtenantcustomer", "description": "Link Customer Profile to Tenant Store", "body": { "moduleid": 1, "tenantid": 8, "locationid": 2, "customerid": 4082, "customerlocationid": 554, "status": 1 } },
+ { "name": "Create New Geofenced Store Location", "method": "POST", "url": "/live/api/v1/web/tenants/createlocation", "description": "Create New Geofenced Store Location", "body": { "tenantid": 8, "applocationid": 1, "moduleid": 1, "locationname": "Hawthorn Daily Fresh Store", "email": "hawthorn.store@merchant.com", "contactno": "399443322", "latitude": "-37.8222", "longitude": "145.0384", "address": "12 Glenferrie Rd", "suburb": "Hawthorn", "city": "Melbourne", "state": "VIC", "postcode": "3122", "opentime": "07:00:00", "closetime": "22:00:00", "partnerid": 1, "deliveryradius": 5000, "deliverymins": 30, "cancelsecs": 60, "status": "Active" } },
+ { "name": "Update Store Location Configurations", "method": "PUT", "url": "/live/api/v1/web/tenants/updatelocation", "description": "Update Store Location Configurations", "body": { "locationid": 2, "tenantid": 8, "applocationid": 1, "locationname": "Richmond Daily Fresh Store", "email": "richmond.store@merchant.com", "contactno": "399887766", "latitude": "-37.8212", "longitude": "144.9984", "address": "Shop 4, 100 Church St", "suburb": "Richmond", "city": "Melbourne", "state": "VIC", "postcode": "3121", "opentime": "07:00:00", "closetime": "22:00:00", "deliveryradius": 8000, "deliverymins": 45, "cancelsecs": 120, "status": "Active" } },
+ { "name": "Onboard New Tenant & Admin Profile", "method": "POST", "url": "/live/api/v1/mob/tenants/createtenantuser", "description": "Onboard New Tenant & Admin Profile (Joint Creation)", "body": { "tenantname": "Fresh Organic Greens", "configid": 1, "partnerid": 1, "moduleid": 1, "tenanttype": "Enterprise", "firstname": "Arthur", "primaryemail": "arthur@organicgreens.com", "primarycontact": "488999000", "categoryid": 2, "subcategoryid": 12, "address": "400 Chapel St", "suburb": "South Yarra", "city": "Melbourne", "state": "VIC", "postcode": "3141", "applocationid": 1, "approved": 1, "status": "Active" } }
+ ]
+ },
+ {
+ "id": "customers",
+ "name": "Customers",
+ "description": "Customer accounts, addresses, support requests, and search.",
+ "endpoints": [
+ { "name": "Fetch customer profile by ID or Contact (Mobile)", "method": "GET", "url": "/live/api/v1/mob/customers/getbyid?customerid=4082&contactno=9876543210", "description": "Fetch customer profile by ID or Contact (Mobile)" },
+ { "name": "Get customer saved address locations (Mobile)", "method": "GET", "url": "/live/api/v1/mob/customers/getcustomerlocation?customerid=4082", "description": "Get customer saved address locations (Mobile)" },
+ { "name": "Get customer logged support requests (Mobile)", "method": "GET", "url": "/live/api/v1/mob/customers/getcustomerrequests?customerid=4082&pageno=1&pagesize=10", "description": "Get customer logged support requests (Mobile)" },
+ { "name": "Search customer names under a tenant (Mobile)", "method": "GET", "url": "/live/api/v1/mob/customers/search?keyword=Jane&tenantid=8", "description": "Search customer names under a tenant (Mobile)" },
+ { "name": "Retrieve customers linked to a tenant location (Mobile)", "method": "GET", "url": "/live/api/v1/mob/customers/gettenantcustomers?tenantid=8&locationid=2&pageno=1&pagesize=10", "description": "Retrieve customers linked to a tenant location (Mobile)" },
+ { "name": "Retrieve merchant customers list (Web)", "method": "GET", "url": "/live/api/v1/web/customers/gettenantcustomers?tenantid=8&locationid=2&pageno=1&pagesize=10&keyword=jane", "description": "Retrieve merchant customers list (Web)" },
+ { "name": "Individual consumer invoice histories (Web)", "method": "GET", "url": "/live/api/v1/web/orders/customer/getorders?customerid=4082&status=delivered&pageno=1&pagesize=10", "description": "Individual consumer invoice histories (Web)" },
+ { "name": "Passwordless OTP Login (via Phone)", "method": "POST", "url": "/live/api/v1/mob/customers/login", "description": "Passwordless OTP Login (via Phone)", "body": { "contactno": "0499888777" } },
+ { "name": "Register Customer Account", "method": "POST", "url": "/live/api/v1/mob/customers/create", "description": "Register Customer Account", "body": { "firstname": "Jane", "lastname": "Smith", "gender": "Female", "dob": "1994-11-20", "dialcode": "+61", "contactno": "499888777", "email": "jane.smith@gmail.com", "deviceid": "uuid_7728b991a", "devicetype": "ios", "authmode": 1, "address": "456 Oak Avenue", "suburb": "Richmond", "city": "Melbourne", "state": "VIC", "postcode": "3121", "latitude": "-37.8212", "longitude": "144.9984", "applocationid": 1, "status": 1 } },
+ { "name": "Save New Geofenced Location Address", "method": "POST", "url": "/live/api/v1/mob/customers/createlocations", "description": "Save New Geofenced Location Address", "body": { "customerid": 4082, "address": "123 High Street", "suburb": "Prahran", "city": "Melbourne", "state": "VIC", "postcode": "3181", "latitude": "-37.8502", "longitude": "144.9924", "primaryaddress": 1, "status": 1 } },
+ { "name": "Log Customer Support Ticket Request", "method": "POST", "url": "/live/api/v1/mob/customers/createcustomerrequest", "description": "Log Customer Support Ticket Request", "body": { "customerid": 4082, "tenantid": 8, "apptypeid": 1, "locationid": 2, "subject": "Delay in Morning Milk Delivery", "remarks": "Order scheduled for 7:00 AM hasn't arrived.", "status": 1 } },
+ { "name": "Update Customer Profile Details", "method": "PUT", "url": "/live/api/v1/mob/customers/update", "description": "Update Customer Profile Details", "body": { "customerid": 4082, "firstname": "Jane", "lastname": "Miller", "email": "jane.miller@gmail.com", "contactno": "499888777", "status": 1 } }
+ ]
+ },
+ {
+ "id": "deliveries",
+ "name": "Deliveries",
+ "description": "Delivery dispatch, queues, summaries, and rider status tracking.",
+ "endpoints": [
+ { "name": "Get deliveries performance summaries (Web)", "method": "GET", "url": "/live/api/v1/web/deliveries/deliverysummary?tenantid=8&partnerid=1&userid=12&applocationid=1&locationid=2&fromdate=2026-05-20&todate=2026-05-20", "description": "Get deliveries performance summaries (Web)" },
+ { "name": "Get daily delivery insights (Web)", "method": "GET", "url": "/live/api/v1/web/deliveries/getdeliveryinsight?tenantid=8", "description": "Get daily delivery insights (Web)" },
+ { "name": "Get location deliveries summary (Web)", "method": "GET", "url": "/live/api/v1/web/deliveries/getlocationsummary?tenantid=8", "description": "Get location deliveries summary (Web)" },
+ { "name": "Get deliveries financial report summary (Web)", "method": "GET", "url": "/live/api/v1/web/deliveries/getreportsummary?tenantid=8&partnerid=1&userid=12&applocationid=1&fromdate=2026-05-01&todate=2026-05-20", "description": "Get deliveries financial report summary (Web)" },
+ { "name": "Get fleet rider summary metrics (Web)", "method": "GET", "url": "/live/api/v1/web/deliveries/getridersummary?applocationid=1&partnerid=1&tenantid=8&fromdate=2026-05-20&todate=2026-05-20", "description": "Get fleet rider summary metrics (Web)" },
+ { "name": "Get master deliveries board (Web)", "method": "GET", "url": "/live/api/v1/web/deliveries/getdeliveries?tenantid=8&fromdate=2026-05-20&todate=2026-05-20", "description": "Get master deliveries board (Web)" },
+ { "name": "Get mobile dispatch summaries (Mobile)", "method": "GET", "url": "/live/api/v1/mob/deliveries/deliverysummary?userid=15&fromdate=2026-05-20&todate=2026-05-20", "description": "Get mobile dispatch summaries (Mobile)" },
+ { "name": "Get mobile deliveries board (Mobile)", "method": "GET", "url": "/live/api/v1/mob/deliveries/getdeliveries?userid=15&status=assigned", "description": "Get mobile deliveries board (Mobile)" },
+ { "name": "Fetch rider active shift deliveries queue (Mobile)", "method": "GET", "url": "/live/api/v1/mob/deliveries/getdeliveryqueues?userid=15&fromdate=2026-05-20&todate=2026-05-20", "description": "Fetch rider active shift deliveries queue (Mobile)" },
+ { "name": "Initialize Logistics Delivery Dispatch (Assign Rider)", "method": "POST", "url": "/live/api/v1/web/deliveries/createdeliveries", "description": "Initialize Logistics Delivery Dispatch", "body": [{ "orderheaderid": 2100, "applocationid": 1, "partnerid": 1, "tenantid": 8, "moduleid": 1, "locationid": 2, "userid": 15, "orderid": "ORD-19028-4", "deliverydate": "2026-05-20", "orderstatus": "assigned", "assigntime": "2026-05-20 12:10:00", "itemcount": 2, "orderamount": 12.58, "customerid": 4082, "pickupcustomer": "Central Merchant Warehouse", "pickupcontactno": "987654321", "pickuplocationid": 2, "pickupaddress": "Shop 4, Central Plaza, Melbourne", "pickuplat": "-37.8136", "pickuplon": "144.9631", "deliverycustomerid": 4082, "deliverylocationid": 554, "deliverycustomer": "Jane Smith", "deliverycontactno": "499888777", "deliveryaddress": "456 Oak Avenue, Richmond, VIC, 3121", "droplat": "-37.8212", "droplon": "144.9984", "deliverycharges": 3, "deliveryamt": 15.58, "deliverytype": "standard", "paymenttype": 1 }] },
+ { "name": "Update Rider Pickup Status", "method": "PUT", "url": "/live/api/v1/web/deliveries/updatedelivery", "description": "Update Rider Pickup Status", "body": { "deliveryid": 8871, "orderheaderid": 2100, "userid": 15, "orderstatus": "picked", "pickuptime": "2026-05-20 12:20:00", "riderslat": "-37.8140", "riderslon": "144.9640" } },
+ { "name": "Rider Update Dispatch Status (Delivered)", "method": "PUT", "url": "/live/api/v1/mob/deliveries/updatedelivery", "description": "Rider Update Dispatch Status (Delivered & GPS Tracking)", "body": { "deliveryid": 8871, "orderheaderid": 2100, "userid": 15, "orderstatus": "delivered", "deliverytime": "2026-05-20 12:45:00", "riderslat": "-37.8210", "riderslon": "144.9980", "actualkms": "4.2", "feedback": "Handed over safely.", "smsdelivery": 1 } }
+ ]
+ },
+ {
+ "id": "orders",
+ "name": "Orders",
+ "description": "Order boards, details, summaries, and status management.",
+ "endpoints": [
+ { "name": "Filtered dynamic orders board (Web)", "method": "GET", "url": "/live/api/v1/web/orders/getorders?tenantid=8&locationid=2&status=processing&pageno=1&pagesize=10", "description": "Filtered dynamic orders board (Web)" },
+ { "name": "System Admin orders board (Web)", "method": "GET", "url": "/live/api/v1/web/orders/admin/getorders?applocationid=1&status=processing&pageno=1&pagesize=10", "description": "System Admin orders board (Web)" },
+ { "name": "Get order dashboard stats summary (Web)", "method": "GET", "url": "/live/api/v1/web/orders/getordersummary?tenantid=8&fromdate=2026-05-01&todate=2026-05-20", "description": "Get order dashboard stats summary (Web)" },
+ { "name": "Get location orders summary (Web)", "method": "GET", "url": "/live/api/v1/web/orders/getlocationsummary?tenantid=8", "description": "Get location orders summary (Web)" },
+ { "name": "Get annual orders insights analytics (Web)", "method": "GET", "url": "/live/api/v1/web/orders/getorderinsight?tenantid=8", "description": "Get annual orders insights analytics (Web)" },
+ { "name": "Get order detailed lines (Web)", "method": "GET", "url": "/live/api/v1/web/orders/getorderdetails?orderheaderid=2099", "description": "Get order detailed lines (Web)" },
+ { "name": "Get customer order history (Mobile)", "method": "GET", "url": "/live/api/v1/mob/orders/getcustomerorders?customerid=4082&pageno=1&pagesize=10", "description": "Get customer order history (Mobile)" },
+ { "name": "Get mobile order detailed lines (Mobile)", "method": "GET", "url": "/live/api/v1/mob/orders/getorderdetails?orderheaderid=2099", "description": "Get mobile order detailed lines (Mobile)" },
+ { "name": "Create New Web Order", "method": "POST", "url": "/live/api/v1/web/orders/createorder", "description": "Create New Web Order (Flat JSON Format)", "body": { "tenantid": 8, "locationid": 2, "applocationid": 1, "moduleid": 1, "customerid": 4082, "orderstatus": "pending", "deliverytype": "standard", "deliverytime": "2026-05-20 18:00:00", "pickupaddress": "Shop 4, Central Plaza, Melbourne", "pickuplat": "-37.8136", "pickuplong": "144.9631", "pickupcustomer": "Central Plaza Merchant", "pickupcontactno": "399887766", "deliveryaddress": "Apt 4B, Sunset Boulevard, Richmond", "deliverylat": "-37.8212", "deliverylong": "144.9984", "orderamount": 11.48, "taxamount": 1.1, "ordervalue": 12.58, "itemcount": 2, "paymenttype": 1, "paymentstatus": 0, "deliverycharge": 3, "items": [{ "productid": 105, "productname": "Organic Whole Milk 1L", "orderqty": 2, "price": 3.99, "taxpercentage": 10, "taxamount": 0.8, "productsumprice": 7.98 }] } },
+ { "name": "Update Order Status & Financial Flag", "method": "PUT", "url": "/live/api/v1/web/orders/updateorder", "description": "Update Order Status & Financial Flag", "body": { "orderheaderid": 2099, "orderstatus": "ready", "paymentstatus": 1, "remarks": "Order packed and waiting for rider assignment." } },
+ { "name": "Create Mobile Order", "method": "POST", "url": "/live/api/v1/mob/orders/createorder", "description": "Create Mobile Order (Wrapped JSON Format)", "body": { "orders": { "tenantid": 8, "locationid": 2, "applocationid": 1, "moduleid": 1, "customerid": 4082, "orderstatus": "pending", "deliverytype": "standard", "deliverytime": "2026-05-20 18:00:00", "pickupaddress": "Shop 4, Central Plaza, Melbourne", "orderamount": 11.48, "taxamount": 1.1, "ordervalue": 12.58, "itemcount": 2, "paymenttype": 1, "paymentstatus": 0, "deliverycharge": 3, "items": [{ "productid": 105, "productname": "Organic Whole Milk 1L", "orderqty": 2, "price": 3.99, "taxpercentage": 10, "taxamount": 0.8, "productsumprice": 7.98 }] } } },
+ { "name": "Mobile Update Order Status", "method": "PUT", "url": "/live/api/v1/mob/orders/updateorder", "description": "Mobile Update Order Status", "body": { "orderheaderid": 2099, "orderstatus": "ready", "paymentstatus": 1, "remarks": "Order packed and waiting for rider assignment." } }
+ ]
+ },
+ {
+ "id": "products",
+ "name": "Products",
+ "description": "Product catalog, stock management, variants, and outlet inventory.",
+ "endpoints": [
+ { "name": "Get product subcategories (Web)", "method": "GET", "url": "/live/api/v1/web/products/getproductsubcategories?categoryid=2&tenantid=8", "description": "Get product subcategories (Web)" },
+ { "name": "Get products stock counts (Web)", "method": "GET", "url": "/live/api/v1/web/products/getproductscount?tenantid=8&categoryid=2&subcategoryid=12&approve=1", "description": "Get products stock counts (Web)" },
+ { "name": "Get all global categories (Web)", "method": "GET", "url": "/live/api/v1/web/products/getproductcategories", "description": "Get all global categories (Web)" },
+ { "name": "Get specific product variants (Web)", "method": "GET", "url": "/live/api/v1/web/products/getproductvariants?tenantid=8&subcategoryid=12", "description": "Get specific product variants (Web)" },
+ { "name": "Get master catalog listings (Web)", "method": "GET", "url": "/live/api/v1/web/products/getcatalougeproducts?tenantid=8&locationid=2&subcategoryid=12&keyword=&pageno=1&pagesize=10", "description": "Get master catalog listings (Web)" },
+ { "name": "Get live stocks catalog (Web)", "method": "GET", "url": "/live/api/v1/web/products/getproductstocks?tenantid=8&locationid=2", "description": "Get live stocks catalog (Web)" },
+ { "name": "Get dynamic stock statement ledger (Web)", "method": "GET", "url": "/live/api/v1/web/products/getstockstatement?tenantid=8&locationid=2&subcategoryid=12&pageno=1&pagesize=10&keyword=", "description": "Get dynamic stock statement ledger (Web)" },
+ { "name": "Get outlet geofenced inventory (Web)", "method": "GET", "url": "/live/api/v1/web/products/getlocationproducts?tenantid=8&locationid=2&subcategoryid=12&pageno=1&pagesize=10", "description": "Get outlet geofenced inventory (Web)" },
+ { "name": "Master products search board (Web)", "method": "GET", "url": "/live/api/v1/web/products/getallproducts?tenantid=8&locationid=2&keyword=milk&pageno=1&pagesize=10", "description": "Master products search board (Web)" },
+ { "name": "Get product details by variant ID (Mobile)", "method": "GET", "url": "/live/api/v1/mob/products/getproductbyvariant?tenantid=8&variantid=4", "description": "Get product details by variant ID (Mobile)" },
+ { "name": "Get product subcategories (Mobile)", "method": "GET", "url": "/live/api/v1/mob/products/getproductsubcategories?categoryid=2&tenantid=8", "description": "Get product subcategories (Mobile)" },
+ { "name": "Search product catalog (Mobile)", "method": "GET", "url": "/live/api/v1/mob/products/getallproducts?keyword=milk&pageno=1&pagesize=10", "description": "Search product catalog (Mobile)" },
+ { "name": "Get mobile geofenced outlet products (Mobile)", "method": "GET", "url": "/live/api/v1/mob/products/getlocationproducts?tenantid=8&locationid=2&pageno=1&pagesize=20", "description": "Get mobile geofenced outlet products (Mobile)" },
+ { "name": "Add Multi-Product Stock Entry", "method": "POST", "url": "/live/api/v1/web/products/createproductstock", "description": "Add Multi-Product Stock Entry", "body": [{ "tenantid": 8, "locationid": 2, "productid": 105, "quantity": 150, "stocktype": "credit", "status": "active" }, { "tenantid": 8, "locationid": 2, "productid": 109, "quantity": 80, "stocktype": "credit", "status": "active" }] },
+ { "name": "Create Master Product Catalog Item", "method": "POST", "url": "/live/api/v1/web/products/create", "description": "Create Master Product Catalog Item", "body": { "applocationid": 1, "tenantid": 8, "categoryid": 2, "subcategoryid": 12, "productname": "Fresh Cow Milk 1L", "productunit": "Litre", "unitvalue": "1", "productcost": 1.8, "retailprice": 3.5, "taxpercent": 5, "productstock": 100, "productstatus": "available", "approve": 1 } },
+ { "name": "Update Master Product Details", "method": "PUT", "url": "/live/api/v1/web/products/update", "description": "Update Master Product Details", "body": { "productid": 105, "productname": "Organic Farm Cow Milk 1L", "productcost": 1.95, "retailprice": 3.75, "productstock": 120, "productstatus": "available" } },
+ { "name": "Purge Master Product Catalog Entry", "method": "DELETE", "url": "/live/api/v1/web/products/delete?productid=105", "description": "Purge Master Product Catalog Entry" }
+ ]
+ },
+ {
+ "id": "invoice",
+ "name": "Invoice",
+ "description": "Invoice insights and billing analytics.",
+ "endpoints": [
+ { "name": "Get invoice insights for a tenant", "method": "GET", "url": "/live/api/v1/web/invoice/getinvoiceinsight?tenantid=8", "description": "Retrieve invoice insights and statistics for a tenant." }
+ ]
+ },
+ {
+ "id": "payments",
+ "name": "Payments",
+ "description": "Payment requests and settlement records.",
+ "endpoints": [
+ { "name": "Get payment requests for a partner", "method": "GET", "url": "/live/api/v1/web/payments/requests/getpaymentrequest?partnerid=44&status=1", "description": "List payment requests for a partner by status." }
+ ]
+ }
+];
diff --git a/src/lib/highlight.js b/src/lib/highlight.js
new file mode 100644
index 0000000..e053f5b
--- /dev/null
+++ b/src/lib/highlight.js
@@ -0,0 +1,26 @@
+const TOKEN = /("(?:\\u[a-fA-F0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(?:true|false|null)\b|-?\d+(?:\.\d+)?(?:[eE][+\-]?\d+)?)/g
+
+function escapeHtml(s) {
+ return s.replace(/&/g, '&').replace(//g, '>')
+}
+
+export function highlightJSON(value) {
+ let text
+ try {
+ text = JSON.stringify(value, null, 2)
+ } catch {
+ text = String(value)
+ }
+ if (typeof text !== 'string') text = String(text)
+ return escapeHtml(text).replace(TOKEN, (match) => {
+ let cls = 'text-amber-300'
+ if (/^"/.test(match)) {
+ cls = /:$/.test(match) ? 'text-sky-300' : 'text-emerald-300'
+ } else if (match === 'true' || match === 'false') {
+ cls = 'text-violet-300'
+ } else if (match === 'null') {
+ cls = 'text-rose-300'
+ }
+ return `${match} `
+ })
+}
diff --git a/test_portal.py b/test_portal.py
new file mode 100644
index 0000000..1dc0d29
--- /dev/null
+++ b/test_portal.py
@@ -0,0 +1,39 @@
+import urllib.request
+import urllib.error
+import time
+
+URL = "https://developer.nearledaily.com/"
+
+def test_portal():
+ print(f"Testing connectivity to {URL}...\n")
+ try:
+ start_time = time.time()
+
+ # Send a standard GET request with a user-agent
+ req = urllib.request.Request(URL, headers={'User-Agent': 'Mozilla/5.0'})
+ with urllib.request.urlopen(req) as response:
+ status_code = response.getcode()
+ html = response.read().decode('utf-8')
+ duration = round((time.time() - start_time) * 1000, 2)
+
+ if status_code == 200:
+ print(f"[SUCCESS] Server responded with HTTP 200 OK in {duration}ms!")
+
+ # Check for specific title tags or branding we added
+ if "NearleDaily API" in html or "nearledaily-docs" in html.lower() or "nearledaily" in html.lower():
+ print("[SUCCESS] Found NearleDaily branding in the page HTML. The app is serving the correct files!")
+ else:
+ print("[WARNING] Server responded with 200 OK, but couldn't find the expected React app HTML.")
+ else:
+ print(f"[ERROR] Server responded with unexpected status code: {status_code}")
+
+ except urllib.error.HTTPError as e:
+ print(f"[HTTP ERROR] The server responded, but returned an error status code: {e.code}")
+ except urllib.error.URLError as e:
+ print(f"[NETWORK ERROR] Failed to reach the server. Reason: {e.reason}")
+ print("Hint: If you just changed the DNS or Coolify port, wait a minute for it to apply/propagate.")
+ except Exception as e:
+ print(f"[UNEXPECTED ERROR] {str(e)}")
+
+if __name__ == "__main__":
+ test_portal()