Reaching Into a Service
The seven endpoints reaching the panel behind a service.
Overview
Behind a service there is usually a panel: a hosting control panel, a virtualisation interface or a software installation. These seven endpoints reach it.
They are all live calls: WISECP returns the panel's state at that moment rather than its own records. A slow panel makes a slow answer, and a panel that is down makes the endpoint fail.
What is opened to the customer is kept narrow next to the admin side. Creating, suspending and terminating are never reachable here.
Reference
Reading the Panel Overview
Returns the overview and the abilities of the panel behind the service.
curl 'https://panel.example.com/api/v1/client/services/622/dashboard' \
-H "Authorization: Bearer $CLIENT_KEY"const res = await fetch(`https://panel.example.com/api/v1/client/services/${id}/dashboard`, {
headers: { Authorization: `Bearer ${clientKey}` },
});
const { data } = await res.json();
if (data.sso_available) showOpenPanelButton();$ch = curl_init('https://panel.example.com/api/v1/client/services/' . $id . '/dashboard');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $clientKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// This call goes LIVE TO THE PANEL: a slow panel makes a slow answer, so cache it on screen.
$d = Kernel::internal('client:Services/GetServiceDashboard',
['owner_id' => $uid, 'id' => $id])['data'];
$can = $d['methods'];Listing the Tools
Returns the panel tools the service offers.
curl 'https://panel.example.com/api/v1/client/services/622/tools' \
-H "Authorization: Bearer $CLIENT_KEY"const res = await fetch(`https://panel.example.com/api/v1/client/services/${id}/tools`, {
headers: { Authorization: `Bearer ${clientKey}` },
});
const { data } = await res.json();
const byGroup = Object.groupBy(data, (t) => t.group);$ch = curl_init('https://panel.example.com/api/v1/client/services/' . $id . '/tools');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $clientKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The customer list is NARROWER than the admin one: the tools opened to the customer area come alone.
$tools = Kernel::internal('client:Services/GetServiceTools',
['owner_id' => $uid, 'id' => $id])['data'];
$keys = array_column($tools, 'key');Reading a Tool's Data
Pulls what a tool lists from the panel.
curl 'https://panel.example.com/api/v1/client/services/622/tools/databases' \
-H "Authorization: Bearer $CLIENT_KEY"const res = await fetch(`https://panel.example.com/api/v1/client/services/${id}/tools/${tool}`, {
headers: { Authorization: `Bearer ${clientKey}` },
});
const { data } = await res.json();$ch = curl_init('https://panel.example.com/api/v1/client/services/' . $id . '/tools/' . $tool);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $clientKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The shape belongs to THE MODULE and is no API contract: the fields move when the server panel does.
$rows = Kernel::internal('client:Services/GetServiceToolData',
['owner_id' => $uid, 'id' => $id, 'tool' => $tool])['data'];Running a Tool Action
Runs a create, an edit or a removal on a tool.
curl -X POST 'https://panel.example.com/api/v1/client/services/622/tools/databases/create' \
-H "Authorization: Bearer $CLIENT_KEY" \
-H 'Content-Type: application/json' \
-d '{"name":"shop"}'const res = await fetch(`https://panel.example.com/api/v1/client/services/${id}/tools/${tool}/${action}`, {
method: 'POST',
headers: {
Authorization: `Bearer ${clientKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
const { data } = await res.json();$ch = curl_init('https://panel.example.com/api/v1/client/services/' . $id . '/tools/' . $tool . '/' . $action);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $clientKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// This call makes a real change ON THE SERVER and cannot be undone: put a removal behind a confirmation.
$out = Kernel::internal('client:Services/RunServiceToolAction',
['owner_id' => $uid, 'id' => $id, 'tool' => $tool, 'action' => 'create'] + $payload);Running a Module Method
Runs a method the module opened to the customer.
curl -X POST 'https://panel.example.com/api/v1/client/services/622/module-method' \
-H "Authorization: Bearer $CLIENT_KEY" \
-H 'Content-Type: application/json' \
-d '{"method":"backup_download"}'const res = await fetch(`https://panel.example.com/api/v1/client/services/${id}/module-method`, {
method: 'POST',
headers: {
Authorization: `Bearer ${clientKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ method }),
});
const { data } = await res.json();
if (data.redirect_url) window.location = data.redirect_url;$ch = curl_init('https://panel.example.com/api/v1/client/services/' . $id . '/module-method');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $clientKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['method' => $method]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// DECLARED methods alone can be called: creating, suspending and terminating are never reachable here.
$d = Kernel::internal('client:Services/GetServiceDashboard',
['owner_id' => $uid, 'id' => $id])['data'];
if (in_array($method, $d['methods'], true))
Kernel::internal('client:Services/UseServiceModuleMethod',
['owner_id' => $uid, 'id' => $id, 'method' => $method]);Signing Into the Panel
Makes a one-time address for signing into the panel without a password.
curl -X POST 'https://panel.example.com/api/v1/client/services/622/sso' \
-H "Authorization: Bearer $CLIENT_KEY"const res = await fetch(`https://panel.example.com/api/v1/client/services/${id}/sso`, {
method: 'POST',
headers: { Authorization: `Bearer ${clientKey}` },
});
const { data } = await res.json();
window.open(data.url, '_blank');$ch = curl_init('https://panel.example.com/api/v1/client/services/' . $id . '/sso');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $clientKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The address is SHORT-LIVED and single use: never cache it and make a new one on each open.
$sso = Kernel::internal('client:Services/GetServiceSso',
['owner_id' => $uid, 'id' => $id])['data'];
header('Location: ' . $sso['url']);Changing the Panel Password
Changes the panel password of the service.
curl -X POST 'https://panel.example.com/api/v1/client/services/622/password' \
-H "Authorization: Bearer $CLIENT_KEY" \
-H 'Content-Type: application/json' \
-d '{"password":"a-long-new-secret"}'const res = await fetch(`https://panel.example.com/api/v1/client/services/${id}/password`, {
method: 'POST',
headers: {
Authorization: `Bearer ${clientKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ password }),
});
if (res.status === 422) showRule(await res.json());$ch = curl_init('https://panel.example.com/api/v1/client/services/' . $id . '/password');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $clientKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['password' => $new]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The panel password is not THE ACCOUNT password: a change here never touches the customer's sign-in.
$d = Kernel::internal('client:Services/GetServiceDashboard',
['owner_id' => $uid, 'id' => $id])['data'];
if ($d['can_change_password'])
Kernel::internal('client:Services/ChangeServicePassword',
['owner_id' => $uid, 'id' => $id, 'password' => $new]);Pitfalls
The overview, the tools and the tool data come from the panel itself rather than the WISECP database. A slow panel makes a long answer and an unreachable one makes the endpoint fail. Do not call these once per row on a listing screen; call them when the user truly asks.
The method endpoint takes the methods a module declared open to the customer. The breadth of the admin side is absent: creating, suspending and terminating are never reachable here. Read the list from the panel overview.
What a tool endpoint returns is the module's own output and can move when the server panel does. An interface bound tightly to the field names breaks on a module update. Read the capabilities from the tool listing and build from those.
Where the operator turns access restriction on for a product, both single sign-on and the panel password change close, and the sign-in details drop from the overview. The tools keep working. Read the two flags in the overview rather than treating it as a fault.
The single sign-on address is short-lived and single use. Keeping it somewhere and opening it later does not work, and while it lives it carries the right to sign in. Make a new one on each open and write it to no log.
The password changed here belongs to the panel on the server and the customer's WISECP sign-in is untouched. The ability exists on hosting and server services alone, and the module has to support it.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.