Service Tools

8 Aufrufe Markdown

The five endpoints that run the provider panel's tools, call module methods and produce sign-in links.

Overview

Tools let you do through the API what the service's provider panel does: create a database, add a mailbox, look at files. You get the same data the panel sees, but raw instead of as HTML.

Tools exist on hosting and server services only. Domain services have their own endpoints, and special products have no tool system at all — they use the module method route instead, which is where power operations, console details and the like are called.

Reference

Listing the Tools

get/api/v1/admin/services/{id}/tools
Services/GetServiceTools admin hosting and servers

Returns the tools the service's module offers and which operations each accepts.

Response fields data[] — 5
keystringThe tool key. The other endpoints use it in the path.
groupstringThe group the tool sits in.
labelstringThe display label.
iconstringThe icon class.
capabilitiesstring[]The operations the tool accepts. Calling one that is not listed is refused.
Errors 3
not_found404No such service.
tools_not_supported422This service type exposes no tools. Domain and special products have none.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/services/506/tools' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/services/506/tools', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/tools');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Read the capability before trying an operation: modules support tools to different degrees.
$tools = Api::Services()->GetServiceTools(['id' => 506])['data'];

foreach ($tools as $tool) {
    $canCreate = in_array('create', $tool['capabilities'], true);
}
Response
{
  "data": [
    {
      "key": "databases",
      "group": "databases",
      "label": "Databases",
      "icon": "bi bi-database",
      "capabilities": ["list", "create", "delete"]
    },
    {
      "key": "email-accounts",
      "group": "email",
      "label": "Email Accounts",
      "icon": "bi bi-envelope",
      "capabilities": ["list", "create", "edit", "delete"]
    }
  ]
}
{
  "error": {
    "code": "tools_not_supported",
    "message": "This service type does not expose tools."
  }
}

Reading a Tool

get/api/v1/admin/services/{id}/tools/{tool}
Services/GetServiceToolData admin the shape comes from the module

Returns what the tool read from the provider, in its raw form.

Query parameters 2
actionstringThe sub-operation passed to the module. It defaults to the tool's index view.
*mixedAny other query parameter you give is passed straight to the module.
Response fields data
datamixedThe tool's own data. Its shape depends entirely on the module and the tool; there is no fixed schema.
Errors 5
not_found404The tool was not found or is not supported.
tools_not_supported422This service type exposes no tools. Domain and special products have none.
tool_required422The tool key was empty.
tool_data_failed500The module could not fetch the data.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/services/506/tools/databases' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/services/506/tools/databases', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/tools/databases');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The panel renders HTML, the API returns RAW data: the shape differs between modules.
$response = Api::Services()->GetServiceToolData(
    ['id' => 506, 'tool' => 'databases'],
);
Response
{
  "data": {
    "databases": [
      {
        "name": "user_app",
        "size": 50855321,
        "tables": 42,
        "users": ["user_admin"]
      }
    ],
    "users": ["user_admin"],
    "prefix": "user_"
  }
}

Running a Tool Operation

post/api/v1/admin/services/{id}/tools/{tool}/{action}
Services/RunServiceToolAction admin runs on the server

Runs an operation on the tool. The module's own validation checks the body fields.

Body *
*mixedWhatever the operation expects. The module decides; the fields are sanitised, validated and written to the history.
Response fields data
datamixedThe module's result. Usually a status and a message.
Errors 4
not_found404The tool was not found or is not supported.
tools_not_supported422This service type exposes no tools. Domain and special products have none.
tool_action_failed500The module could not complete the operation.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/services/506/tools/databases/create' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"name":"user_app"}'
const res = await fetch('https://panel.example.com/api/v1/admin/services/506/tools/databases/create', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: 'user_app' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/tools/databases/create');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['name' => 'user_app']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The operation really runs ON THE SERVER: delete calls cannot be undone.
$response = Api::Services()->RunServiceToolAction(
    ['id' => 506, 'tool' => 'databases', 'action' => 'create'],
    [],
    ['name' => 'user_app'],
);

Calling a Module Method

post/api/v1/admin/services/{id}/module-method
Services/UseServiceModuleMethod admin bound to an allow list

Calls a method the module allows. This is the way in for service types with no tool system.

Body 2
methodstringrequiredName of the method to call. Only methods on the module's callable list, or with a matching handler, will run.
*mixedAny other field you give is passed to the method as a parameter.
Response fields data — 4
methodstringThe method that was called.
redirect_urlstring | nullThe address, when the method produced a redirect.
resultmixed | nullWhat the method returned. Filled only when it returns an array or a string.
outputstring | nullAnything the method printed.
Errors 5
not_found404No such service.
method_required422No method name was given.
invalid_method422The method is not callable on the module.
no_module422The service has no module attached.
module_method_failed500The method threw an error.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/services/506/module-method' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"method":"vnc_info"}'
const res = await fetch('https://panel.example.com/api/v1/admin/services/506/module-method', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ method: 'vnc_info' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/module-method');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['method' => 'vnc_info']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The outcome can arrive in three different fields: a return value, printed output, or a redirect.
$response = Api::Services()->UseServiceModuleMethod([
    'id'     => 506,
    'method' => 'vnc_info',
]);

$data = $response['data']['result']
    ?? $response['data']['output']
    ?? $response['data']['redirect_url'];
Response
{
  "data": {
    "method": "vnc_info",
    "redirect_url": null,
    "result": { "host": "203.0.113.10", "port": 5901 },
    "output": null
  }
}
{
  "error": {
    "code": "invalid_method",
    "message": "Module method is not callable."
  }
}

A Sign-in Link for the Panel

post/api/v1/admin/services/{id}/sso
Services/GetServiceSso admin one-click sign-in

Produces a one-click sign-in link for the service's panel.

Body 1
rootboolProduces an administrator sign-in. Off by default, and while off it signs in to the client's own account.
Response fields data — 2
urlstringThe sign-in link.
rootboolWhether an administrator sign-in was asked for.
Errors 4
not_found404No such service.
sso_not_supported422The module does not support one-click sign-in.
sso_failed500The module produced no link.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/services/506/sso' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"root":false}'
const res = await fetch('https://panel.example.com/api/v1/admin/services/506/sso', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ root: false }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/sso');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['root' => false]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The link carries a session: keep it out of logs, do not share it, use it quickly.
$response = Api::Services()->GetServiceSso(['id' => 506]);
$url      = $response['data']['url'];

Pitfalls

A tool operation really runs on the server

These endpoints do not update a record; they reach the provider and have the work done there. Delete operations really remove the client's data and cannot be undone. Check the capabilities in the tool list before trying one, since an unsupported operation is refused.

The response shape depends on the module

Tool data comes back raw and its shape differs between modules: one hosting panel returns databases under different keys than another. Parsing written against a single module breaks on the second one, so do not assume a fixed schema.

Module methods run against an allow list

You cannot pick the method name freely: only ones the module marks callable, or that have a matching handler, will run, and the rest answer invalid_method. That is a security boundary, so do not assume every public method on the module is reachable.

Client-side restrictions apply on the API too

Tools switched off for the client on a server are switched off for API calls as well. A tool you can see as an administrator in the panel may be unreachable through the API with the same key, and the reason is the restriction setting on the server rather than your permissions.

The sign-in link carries a session

The link opens a session when clicked. Logging it, storing it or sharing it means sharing access to that account, so treat it as a short-lived credential. A call asking for the administrator sign-in opens the root of the panel, not one client account.

War das hilfreich?

Vielen Dank für Ihre Rückmeldung!

Brauchen Sie weitere Hilfe?

Unser Support-Team ist rund um die Uhr für Sie da, wenn Sie oben nicht fündig werden.