curl --request PATCH \
--url https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Research Associate",
"description": "Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.",
"permissions": [
"team.read",
"server.read",
"server.power",
"server.console",
"server.update",
"backup.read",
"backup.create",
"snapshot.read",
"snapshot.create",
"firewall.read",
"firewall.update",
"network.read",
"sshkey.read",
"sshkey.update"
]
}
'import requests
url = "https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}"
payload = {
"name": "Research Associate",
"description": "Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.",
"permissions": ["team.read", "server.read", "server.power", "server.console", "server.update", "backup.read", "backup.create", "snapshot.read", "snapshot.create", "firewall.read", "firewall.update", "network.read", "sshkey.read", "sshkey.update"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Research Associate',
description: 'Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.',
permissions: [
'team.read',
'server.read',
'server.power',
'server.console',
'server.update',
'backup.read',
'backup.create',
'snapshot.read',
'snapshot.create',
'firewall.read',
'firewall.update',
'network.read',
'sshkey.read',
'sshkey.update'
]
})
};
fetch('https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Research Associate',
'description' => 'Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.',
'permissions' => [
'team.read',
'server.read',
'server.power',
'server.console',
'server.update',
'backup.read',
'backup.create',
'snapshot.read',
'snapshot.create',
'firewall.read',
'firewall.update',
'network.read',
'sshkey.read',
'sshkey.update'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}"
payload := strings.NewReader("{\n \"name\": \"Research Associate\",\n \"description\": \"Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.\",\n \"permissions\": [\n \"team.read\",\n \"server.read\",\n \"server.power\",\n \"server.console\",\n \"server.update\",\n \"backup.read\",\n \"backup.create\",\n \"snapshot.read\",\n \"snapshot.create\",\n \"firewall.read\",\n \"firewall.update\",\n \"network.read\",\n \"sshkey.read\",\n \"sshkey.update\"\n ]\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Research Associate\",\n \"description\": \"Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.\",\n \"permissions\": [\n \"team.read\",\n \"server.read\",\n \"server.power\",\n \"server.console\",\n \"server.update\",\n \"backup.read\",\n \"backup.create\",\n \"snapshot.read\",\n \"snapshot.create\",\n \"firewall.read\",\n \"firewall.update\",\n \"network.read\",\n \"sshkey.read\",\n \"sshkey.update\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Research Associate\",\n \"description\": \"Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.\",\n \"permissions\": [\n \"team.read\",\n \"server.read\",\n \"server.power\",\n \"server.console\",\n \"server.update\",\n \"backup.read\",\n \"backup.create\",\n \"snapshot.read\",\n \"snapshot.create\",\n \"firewall.read\",\n \"firewall.update\",\n \"network.read\",\n \"sshkey.read\",\n \"sshkey.update\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "18f11680-0831-4d41-9d71-824c99009cbf",
"name": "Research Associate",
"description": "Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.",
"permissions": [
"team.read",
"server.read",
"server.power",
"server.console",
"server.update",
"backup.read",
"backup.create",
"snapshot.read",
"snapshot.create",
"firewall.read",
"firewall.update",
"network.read",
"sshkey.read",
"sshkey.update"
],
"type": "custom",
"system_key": null,
"is_system": false,
"members_count": 1,
"created_at": "2026-01-09T20:14:52+00:00"
}{
"message": "Unauthenticated."
}{
"message": "This API key is not allowed to do that in this team. It needs the \"snapshot.delete\" permission."
}{
"message": "Not found."
}{
"message": "The name field is required.",
"errors": {}
}{
"message": "Too Many Attempts."
}Update a role
Overview
Replaces a role’s name, description and permissions and returns the updated role. Send all three fields. Omitted permissions are removed from every member on their next request. Creation limits apply. Built-in roles and unknown permission keys return 422. You cannot edit a role with more permissions than yours or grant permissions you do not hold.
Permissions
Requires the account permission teams.manage (Manage teams).
curl --request PATCH \
--url https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Research Associate",
"description": "Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.",
"permissions": [
"team.read",
"server.read",
"server.power",
"server.console",
"server.update",
"backup.read",
"backup.create",
"snapshot.read",
"snapshot.create",
"firewall.read",
"firewall.update",
"network.read",
"sshkey.read",
"sshkey.update"
]
}
'import requests
url = "https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}"
payload = {
"name": "Research Associate",
"description": "Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.",
"permissions": ["team.read", "server.read", "server.power", "server.console", "server.update", "backup.read", "backup.create", "snapshot.read", "snapshot.create", "firewall.read", "firewall.update", "network.read", "sshkey.read", "sshkey.update"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Research Associate',
description: 'Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.',
permissions: [
'team.read',
'server.read',
'server.power',
'server.console',
'server.update',
'backup.read',
'backup.create',
'snapshot.read',
'snapshot.create',
'firewall.read',
'firewall.update',
'network.read',
'sshkey.read',
'sshkey.update'
]
})
};
fetch('https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Research Associate',
'description' => 'Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.',
'permissions' => [
'team.read',
'server.read',
'server.power',
'server.console',
'server.update',
'backup.read',
'backup.create',
'snapshot.read',
'snapshot.create',
'firewall.read',
'firewall.update',
'network.read',
'sshkey.read',
'sshkey.update'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}"
payload := strings.NewReader("{\n \"name\": \"Research Associate\",\n \"description\": \"Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.\",\n \"permissions\": [\n \"team.read\",\n \"server.read\",\n \"server.power\",\n \"server.console\",\n \"server.update\",\n \"backup.read\",\n \"backup.create\",\n \"snapshot.read\",\n \"snapshot.create\",\n \"firewall.read\",\n \"firewall.update\",\n \"network.read\",\n \"sshkey.read\",\n \"sshkey.update\"\n ]\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Research Associate\",\n \"description\": \"Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.\",\n \"permissions\": [\n \"team.read\",\n \"server.read\",\n \"server.power\",\n \"server.console\",\n \"server.update\",\n \"backup.read\",\n \"backup.create\",\n \"snapshot.read\",\n \"snapshot.create\",\n \"firewall.read\",\n \"firewall.update\",\n \"network.read\",\n \"sshkey.read\",\n \"sshkey.update\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://console.advinservers.com/api/v1/client/teams/{team}/roles/{role}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Research Associate\",\n \"description\": \"Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.\",\n \"permissions\": [\n \"team.read\",\n \"server.read\",\n \"server.power\",\n \"server.console\",\n \"server.update\",\n \"backup.read\",\n \"backup.create\",\n \"snapshot.read\",\n \"snapshot.create\",\n \"firewall.read\",\n \"firewall.update\",\n \"network.read\",\n \"sshkey.read\",\n \"sshkey.update\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "18f11680-0831-4d41-9d71-824c99009cbf",
"name": "Research Associate",
"description": "Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money.",
"permissions": [
"team.read",
"server.read",
"server.power",
"server.console",
"server.update",
"backup.read",
"backup.create",
"snapshot.read",
"snapshot.create",
"firewall.read",
"firewall.update",
"network.read",
"sshkey.read",
"sshkey.update"
],
"type": "custom",
"system_key": null,
"is_system": false,
"members_count": 1,
"created_at": "2026-01-09T20:14:52+00:00"
}{
"message": "Unauthenticated."
}{
"message": "This API key is not allowed to do that in this team. It needs the \"snapshot.delete\" permission."
}{
"message": "Not found."
}{
"message": "The name field is required.",
"errors": {}
}{
"message": "Too Many Attempts."
}Authorizations
Your API key, sent as a bearer token. Create one in the control panel under API Keys, give it only the permissions the integration needs, and copy it when it is created. It cannot be shown again. Each key is restricted to one owned team. The key determines the team for every request.
Path Parameters
The team UUID
"fbb31f5f-bd6f-4019-a3ed-1062a28f56f7"
The role UUID
"18f11680-0831-4d41-9d71-824c99009cbf"
Body
Send a JSON object containing the fields below. Required fields are marked in the schema.
The name shown to customers.
1 - 64^[^\p{C}]+$The value of permissions.
41Rejected rather than quietly dropped. An account that has just ticked something this release does not have needs to be told, not left believing the role grants it.
team.read, team.manage, server.read, server.power, server.console, server.update, server.credentials, server.reinstall, server.transfer, backup.read, backup.create, backup.restore, backup.delete, snapshot.read, snapshot.create, snapshot.restore, snapshot.delete, snapshot.update, snapshot.transfer, firewall.read, firewall.update, firewall.delete, network.read, network.update, network.transfer, network.delete, sshkey.read, sshkey.update, sshkey.delete, script.read, script.update, script.delete, iso.read, iso.update, iso.delete, measured_boot.read, measured_boot.update, measured_boot.delete, billing.read, billing.manage, billing.purchase An optional description shown to customers.
512^[^\p{C}\n\r]*$Response
The record, as a JSON object. There is no envelope.
A named set of permissions in a team.
The id ID.
"18f11680-0831-4d41-9d71-824c99009cbf"
The name shown to customers.
"Research Associate"
An optional description shown to customers.
"Runs the test chamber servers and takes snapshots before each experiment, but cannot delete, reinstall or spend money."
Read through the model rather than off the column: a seeded role resolves its permissions from the catalogue every time, so it picks up anything added in a later release, and a key that no longer exists is dropped instead of being shown.
[
"team.read",
"server.read",
"server.power",
"server.console",
"server.update",
"backup.read",
"backup.create",
"snapshot.read",
"snapshot.create",
"firewall.read",
"firewall.update",
"network.read",
"sshkey.read",
"sshkey.update"
]
The role type: system or custom.
system, custom "custom"
The value of system_key.
null
The three seeded roles are readable and assignable but never editable or deletable, so an account always has a working set to hand out.
false
Only present when the listing asked for it; a role fetched on its own does not pay for the count.
1
The date and time for created at, in UTC.
"2026-01-09T20:14:52+00:00"