Quick Reads
The four read-only endpoints that search clients, give the counts and fill the summary card.
Overview
These four endpoints tell you something quickly about a client and change nothing. The panel's search box, dashboard counters and summary card all read from them.
Two look across the installation (search and statistics) and two at a single client (summary and the standout note). Whether the path carries a client id tells you which one you are on.
Reference
Searching for a Client
Searches clients by name, company or e-mail. It was written for autocomplete boxes.
search is accepted too.curl -G 'https://panel.example.com/api/v1/admin/clients/search' \
-H "Authorization: Bearer $API_KEY" \
-d q=acmeconst url = new URL('https://panel.example.com/api/v1/admin/clients/search');
url.searchParams.set('q', 'acme');
const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();$url = 'https://panel.example.com/api/v1/admin/clients/search?' . http_build_query(['q' => 'acme']);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->SearchClients([], ['q' => 'acme']);Client Statistics
Returns the counts across every client in the installation. It looks at no single client.
all_time, today, week, month or year. Defaults to all_time.curl -G 'https://panel.example.com/api/v1/admin/clients/stats' \
-H "Authorization: Bearer $API_KEY" \
-d period=monthconst url = new URL('https://panel.example.com/api/v1/admin/clients/stats');
url.searchParams.set('period', 'month');
const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();$url = 'https://panel.example.com/api/v1/admin/clients/stats?' . http_build_query(['period' => 'month']);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->GetClientsStats([], ['period' => 'month']);{
"data": {
"active": 120,
"blocked": 3,
"new": 18,
"blacklisted": 2,
"active_services": 340,
"unpaid_invoices": 41,
"credit_balance": 14620.12,
"growth_rate": 4.5,
"total": 145
}
}Client Summary
Returns summary card data for one client: revenue, service and ticket counts, badges, trust score.
reference/currencies.poor, fair, good ya da excellent.curl 'https://panel.example.com/api/v1/admin/clients/42/summary' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/summary', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/summary');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->GetClientSummary(['id' => 42]);
// The parts tell you where the score came from.
$score = $response['data']['trust_score'];
$fromServices = $score['services'];{
"data": {
"user_id": 9,
"full_name": "Test Client",
"company_name": "",
"created_at": "2021-03-18 00:00:00",
"total_revenue": 36,
"revenue_currency": 4,
"paid_invoices": 1,
"active_services": 16,
"inactive_services": 16,
"total_tickets": 0,
"recent_tickets": 0,
"badges": {
"loyal": true,
"revenue": false,
"multi_service": true,
"experienced": true
},
"trust_score": {
"total": 50,
"label": "fair",
"services": 30,
"revenue": 5,
"age": 15,
"tickets": 0
}
}
}Reading the Standout Note
Returns one of the client's notes: the pinned one if there is one, otherwise the newest.
null when the note is not pinned, or was pinned before this field existed.curl 'https://panel.example.com/api/v1/admin/clients/42/latest-note' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/latest-note', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
// With no notes at all, data comes back null - not a 404.
if (body.data === null) return;$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/latest-note');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->GetClientLatestNote(['id' => 42]);
// On a client with no notes, 'data' is null.
$note = $response['data'] ?? null;Pitfalls
The credit balance and revenue fields are numbers without a symbol, and the date is raw too. You read the currency from its own field and do the formatting yourself. That is deliberate: the server does not know the reader's locale.
On a client with no notes the standout-note endpoint returns data: null, not a 404. Code that reaches straight into the fields breaks here, so check for empty first.
The score in the summary is not a fixed scale; it is worked out from the tiers in your configuration. Change the tiers and the same client scores differently, so do not compare the score across installations.
Related Articles
感谢您的反馈!