Client Configuration
The six endpoints that read and save client groups, badge thresholds and trust score tiers.
Overview
These six endpoints read and write the installation-wide client configuration: groups, badge thresholds and trust score tiers. None of them looks at an individual client.
The trust score is worked out on four axes: service count, revenue, account age and support tickets. Each axis is a list of tiers, and a client scores whatever the tier they fall into is worth.
Reference
Listing the Groups
Returns every client group in the installation.
0 for a new one.#095174.curl 'https://panel.example.com/api/v1/admin/clients/groups' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/clients/groups', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/groups');
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()->GetClientGroups();Saving the Groups
Saves the group list as it stands. The list you send becomes the truth: a group missing from it is deleted.
0 for a new one.#095174.groups is not an array.curl -X PUT 'https://panel.example.com/api/v1/admin/clients/groups' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"groups":[{"id":5,"name":"VIP","discount_rate":10,"discount_products":"1,2","priority":1}]}'// Read the list first, change it, then send all of it back.
const current = await (await fetch('https://panel.example.com/api/v1/admin/clients/groups', {
headers: { Authorization: `Bearer ${apiKey}` },
})).json();
const groups = current.data.map((g) =>
g.id === 5 ? { ...g, discount_rate: 15 } : g);
const res = await fetch('https://panel.example.com/api/v1/admin/clients/groups', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ groups }),
});$ch = curl_init('https://panel.example.com/api/v1/admin/clients/groups');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'groups' => [
[
'id' => 5,
'name' => 'VIP',
'discount_rate' => 10,
'priority' => 1,
],
],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Even to change one group, the WHOLE list goes back.
$groups = Api::Clients()->GetClientGroups()['data'];
foreach ($groups as &$group)
if ((int) $group['id'] === 5) $group['discount_rate'] = 15;
unset($group);
$response = Api::Clients()->SaveClientGroups(['groups' => $groups]);Reading the Badge Thresholds
Returns the thresholds at which client badges are earned. If none were saved, you get the defaults.
curl 'https://panel.example.com/api/v1/admin/clients/badge-settings' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/clients/badge-settings', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/badge-settings');
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()->GetBadgeSettings();Saving the Badge Thresholds
Saves all five thresholds at once. One you leave out drops back to its default, so send the whole set. Values are pulled into a safe range rather than refused.
rev_silver + 1.curl -X PUT 'https://panel.example.com/api/v1/admin/clients/badge-settings' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"loyal_years":5,"rev_silver":500,"rev_gold":1000,"multi_service_min":5,"experienced_max":15}'const res = await fetch('https://panel.example.com/api/v1/admin/clients/badge-settings', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
loyal_years: 5,
rev_silver: 500,
rev_gold: 1000,
multi_service_min: 5,
experienced_max: 15,
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/badge-settings');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'loyal_years' => 5,
'rev_silver' => 500,
'rev_gold' => 1000,
'multi_service_min' => 5,
'experienced_max' => 15,
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->SaveBadgeSettings([
'rev_silver' => 500,
'rev_gold' => 400,
]);
// The response carries what was stored: rev_gold comes back as 501 here.
$saved = $response['data']['rev_gold'];Reading the Trust Score Tiers
Returns the tiers on all four trust score axes. If none were saved, you get the defaults.
null is the last, unbounded tier.null is the last, unbounded tier.null is the last, unbounded tier.null is the last, unbounded tier.curl 'https://panel.example.com/api/v1/admin/clients/trust-score-settings' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/clients/trust-score-settings', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/trust-score-settings');
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()->GetTrustScoreSettings();{
"data": {
"services": [
{ "max": 5, "points": 20 },
{ "max": null, "points": 30 }
],
"revenue": [{ "max": 1000, "points": 25 }],
"age": [{ "max": 12, "points": 10 }],
"tickets": [{ "max": null, "points": 5 }]
}
}Saving the Trust Score Tiers
Saves all four axes at once. An axis you leave out is saved empty and loses its tiers, so send every axis you want to keep.
null is the last, unbounded tier.null is the last, unbounded tier.null is the last, unbounded tier.null is the last, unbounded tier.curl -X PUT 'https://panel.example.com/api/v1/admin/clients/trust-score-settings' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"services":[{"max":5,"points":20},{"max":null,"points":30}]}'const res = await fetch('https://panel.example.com/api/v1/admin/clients/trust-score-settings', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
services: [
{ max: 5, points: 20 },
{ max: null, points: 30 },
],
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/trust-score-settings');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'services' => [
['max' => 5, 'points' => 20],
['max' => null, 'points' => 30],
],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The last tier needs 'max' => null, or a client above the bound scores nothing.
$response = Api::Clients()->SaveTrustScoreSettings([
'services' => [
['max' => 5, 'points' => 20],
['max' => null, 'points' => 30],
],
]);Pitfalls
The save endpoint does not merge. A group missing from the list you send is deleted, and the clients in it are left without one. To change a single group, read the list first, edit it, and send all of it back.
Sending the gold revenue threshold at or below silver does not raise an error; the value quietly becomes rev_silver + 1. Read the response to see what was stored.
Leave max as null on an axis's last tier. Otherwise a client above the highest bound falls into no tier and scores nothing on that axis.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.