Server Groups

7 views Markdown

The five endpoints that manage the server groups letting products provision into a pool.

Overview

A server group lets a product be provisioned into a pool rather than onto one server. The product points at the group, and the fill strategy decides which server a new service lands on.

The group's type is not a field of its own: it comes from the members. That is why only servers on the same type and the same module can go into one group; a mixed list is refused outright.

Reference

Listing the Groups

get/api/v1/admin/products/server-groups
Products/GetServerGroups admin paged

Returns the server groups.

Query parameters 3
searchstringSearches the group name.
pageintDefaults to 1.
limitintDefaults to 25, maximum 100.
Response fields data[] — 6
idintGroup id.
namestringThe group name.
typestringhosting or server. It comes from the members; you do not set it.
fill_typeintThe fill strategy deciding which server a new service lands on.
server_idsint[]Ids of the servers in the group.
server_countintHow many servers are in the group.
Meta 4
totalintTotal records matching the filter.
pageintThe page you are on.
limitintThe page size.
next_pageintThe next page. Zero means you are on the last one.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/products/server-groups' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/products/server-groups', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/products/server-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::Products()->GetServerGroups();
Response
{
  "data": [
    {
      "id": 2,
      "name": "Shared Pool",
      "type": "hosting",
      "fill_type": 1,
      "server_ids": [34, 35],
      "server_count": 2
    }
  ],
  "meta": { "total": 1, "page": 1, "limit": 25, "next_page": 0 }
}

Group Detail

get/api/v1/admin/products/server-groups/{id}
Products/GetServerGroup admin

Returns one server group. The schema is the same as a list item.

Response fields data — 6
idintGroup id.
namestringThe group name.
typestringhosting or server. It comes from the members; you do not set it.
fill_typeintThe fill strategy deciding which server a new service lands on.
server_idsint[]Ids of the servers in the group.
server_countintHow many servers are in the group.
Errors 2
not_found404No such server group.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/products/server-groups/2' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/products/server-groups/2', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/products/server-groups/2');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Products()->GetServerGroup(['id' => 2]);

Creating a Group

post/api/v1/admin/products/server-groups
Products/CreateServerGroup admin 201

Opens a server group. Every member has to share the same type and the same module.

Body 3
namestringrequiredThe group name.
serversint[]requiredIds of the servers to put in. At least one, and all on the same type and module.
fill_typeintThe fill strategy. Defaults to 1.
Response fields data — 6
idintId of the new group.
namestringThe group name.
typestringhosting or server. It comes from the members, so it is never part of the request.
fill_typeintThe fill strategy deciding which server a new service lands on.
server_idsint[]Ids of the servers in the group.
server_countintHow many servers are in the group.
Errors 6
name_required422name was empty.
servers_required422No server was given.
invalid_server422One of the servers you gave does not exist.
no_capacity422One of the servers has no account capacity.
mixed_servers422The servers do not share a type and a module.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/products/server-groups' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Shared Pool","servers":[34,35],"fill_type":1}'
const res = await fetch('https://panel.example.com/api/v1/admin/products/server-groups', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Shared Pool',
    servers: [34, 35],
    fill_type: 1,
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/products/server-groups');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'name'      => 'Shared Pool',
        'servers'   => [34, 35],
        'fill_type' => 1,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Filter out type and module mismatches yourself: a mixed list is refused outright.
$servers = Api::Products()->GetServers([], ['limit' => 100])['data'];
$cpanel  = array_column(
    array_filter($servers, fn (array $s): bool => $s['type'] === 'cPanel'),
    'id',
);

Api::Products()->CreateServerGroup([
    'name'    => 'Shared Pool',
    'servers' => $cpanel,
]);

Updating a Group

patch/api/v1/admin/products/server-groups/{id}
Products/UpdateServerGroup admin the member list is written whole

Applies the fields you send. Send the member list and the group becomes exactly that list.

Body 3
namestringThe group name. If you send it, it cannot be empty.
serversint[]The complete set of servers. A server missing from the list leaves the group.
fill_typeintThe fill strategy.
Response fields data — 6
idintGroup id.
namestringThe group name.
typestringhosting or server. It comes from the members; you do not set it.
fill_typeintThe fill strategy deciding which server a new service lands on.
server_idsint[]Ids of the servers in the group. The up-to-date list, after your change.
server_countintHow many servers are in the group.
Errors 6
not_found404No such server group.
name_required422The group name you sent was empty.
invalid_server422One of the servers you gave does not exist.
no_capacity422One of the servers has no account capacity.
mixed_servers422The servers do not share a type and a module.
insufficient_scope403The key lacks the required scope.
Request
curl -X PATCH 'https://panel.example.com/api/v1/admin/products/server-groups/2' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"servers":[34,35,36]}'
const res = await fetch('https://panel.example.com/api/v1/admin/products/server-groups/2', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ servers: [34, 35, 36] }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/products/server-groups/2');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['servers' => [34, 35, 36]]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// To ADD a server send the current list too, or the others leave the group.
$group = Api::Products()->GetServerGroup(['id' => 2])['data'];

Api::Products()->UpdateServerGroup([
    'id'      => 2,
    'servers' => [...$group['server_ids'], 36],
]);

Deleting a Group

delete/api/v1/admin/products/server-groups/{id}
Products/DeleteServerGroup admin refused while in use

Deletes the server group. The delete is refused while a product still points at it.

Response fields data — 2
deletedboolWhether the delete succeeded.
idintId of the deleted group.
Errors 4
not_found404No such server group.
group_in_use422The group is still used by products.
blocked_by_gate422The gate:product.server_group_delete hook vetoed the operation.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/products/server-groups/2' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/products/server-groups/2', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/products/server-groups/2');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Deleting the group does not delete its members: the servers stay, only the grouping goes.
$response = Api::Products()->DeleteServerGroup(['id' => 2]);

Pitfalls

A mixed list is refused outright

Because the group takes its type from its members, servers on different types or different modules cannot sit together. Send such a list and none of them is added; the request comes back as mixed_servers. Filter the list on your side first.

The member list is written whole

Sending a server list on an update makes the group exactly that list; servers missing from it leave. To add one server, read the current list first, append to it, and send all of it back.

A server with no capacity cannot join

A server with no account capacity cannot be a member, and the request comes back as no_capacity. The fill strategy decides by capacity, so this is not a formality but a working condition.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.