Server Groups
The Server Groups resource provides access to all methods relating to Server Groups management in Keystash. Server Groups are logical groups of servers to allow for quick and easy bulk management of User privileges and SSH service policy.
List Server Groups
Path: /server-groups/list
Method: GET
Authentication: Bearer Token
Request Headers
| Key | Value | Required |
|---|---|---|
Accept-Encoding |
gzip | optional |
Request Parameters
All parameters are optional. Combine as many as you need and they are all applied together.
| Key | Data Type | Required | Notes |
|---|---|---|---|
ids |
array of string | optional | One or more Server Group id values, 1–16 alphanumeric characters each. Note the plural: the resource here is the Server Group. |
name |
string | optional | 1–255 characters. Matches any group whose name contains this value. |
description |
string | optional | 1–255 characters. Matches any group whose description contains this value. |
default_group |
boolean | optional | true, false, 1 or 0. Returns the default Server Group, or everything but it. |
connection_logging |
boolean | optional | true, false, 1 or 0. Filters on whether SSH Connection Logging is enabled for the group. |
password_auth_enabled |
boolean | optional | true, false, 1 or 0. |
two_factor_enabled |
boolean | optional | true, false, 1 or 0. |
two_factor_disallow_reuse |
boolean | optional | true, false, 1 or 0. |
two_factor_allow_unenrolled |
boolean | optional | true, false, 1 or 0. |
start_date |
string | optional | Inclusive lower bound on the group's created date, in UTC YYYY-MM-DD HH:mm:ss. Must be supplied with end_date and must not be later than it. |
end_date |
string | optional | Inclusive upper bound on the group's created date, in UTC YYYY-MM-DD HH:mm:ss. Must be supplied with start_date. |
limit |
integer | optional | Rows to return. Defaults to 250, which is also the maximum; a larger value is reduced to 250. |
offset |
integer | optional | Row offset for paging. Defaults to 0. |
Note
A parameter that is not recognised, or a value that fails its rule, returns a 400 BadArgument naming every parameter at fault. See Filtering Lists for the full rules, and Paging Through Lists for the X-Total-Count, X-Limit and X-Offset headers.
Tip
To find your default Server Group, filter on ?default_group=true rather than reading the first row of the list. Server Groups are returned in name order.
Request Body
None.
Example Request
curl --location --request GET 'https://app.keystash.io/api/v1/server-groups/list' \
--header 'Authorization: Bearer <token>'
Narrowing the list to the groups that enforce Two Factor Authentication:
curl --location --request GET 'https://app.keystash.io/api/v1/server-groups/list?two_factor_enabled=true&limit=50' \
--header 'Authorization: Bearer <token>'
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Total-Count: 2
X-Limit: 250
X-Offset: 0
[
{
"id": "Gfz5m9mGuIp6ByPz",
"name": "Production Servers",
"description": "All production servers.",
"version": 117,
"default_group": true,
"connection_logging": true,
"password_auth_enabled": true,
"two_factor_enabled": false,
"two_factor_disallow_reuse": true,
"two_factor_window_size": 1,
"two_factor_rate_limit": 3,
"two_factor_allow_unenrolled": false,
"created": "2022-04-03 16:03:42",
"created_user_id": "x0Uf09z8TYjoNVFB",
"created_by": "Max Smith",
"modified": "2023-09-25 07:28:22",
"modified_user_id": "x0Uf09z8TYjoNVFB",
"modified_by": "Max Smith"
},
{
"id": "rzbSZtL2zI0oA16V",
"name": "Production Databases",
"description": "",
"version": 85,
"default_group": false,
"connection_logging": false,
"password_auth_enabled": false,
"two_factor_enabled": true,
"two_factor_disallow_reuse": true,
"two_factor_window_size": 2,
"two_factor_rate_limit": 3,
"two_factor_allow_unenrolled": true,
"created": "2022-05-25 12:22:41",
"created_user_id": "x0Uf09z8TYjoNVFB",
"created_by": "Max Smith",
"modified": "2023-09-25 07:28:22",
"modified_user_id": "x0Uf09z8TYjoNVFB",
"modified_by": "Max Smith"
}
]
Example Error Response
Invalid Filter Value (400 Bad Request)
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "BadArgument",
"message": "One or more query parameters were invalid.",
"details": [
{
"field": "two_factor_enabled",
"message": "Expected a boolean value.",
"received": "banana",
"allowed_values": ["true", "false", "1", "0"]
}
]
}
}
No Server Groups (404 Not Found)
A 404 here means your company has no Server Groups at all. A filter that matches nothing returns a 200 OK with an empty array ([]), as does an offset past the end of the results.
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "Your request was successfully processed but there was no data to be returned.",
"details": []
}
}
View Server Group
Path: /server-groups/view
Method: GET
Authentication: Bearer Token
Request Headers
| Key | Value | Required |
|---|---|---|
Accept-Encoding |
gzip | optional |
Request Parameters
| Key | Data Type | Required | Notes |
|---|---|---|---|
id |
string | required | The ID of the server group to view |
Request Body
None.
Example Request
curl --location --request GET 'https://app.keystash.io/api/v1/server-groups/view?id=BD720EP87kNORRcH' \
--header 'Authorization: Bearer <token>'
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"id": "BD720EP87kNORRcH",
"name": "Production Databases",
"description": "",
"version": 633,
"default_group": true,
"connection_logging": true,
"password_auth_enabled": false,
"two_factor_enabled": true,
"two_factor_disallow_reuse": true,
"two_factor_window_size": 1,
"two_factor_rate_limit": 3,
"two_factor_allow_unenrolled": false,
"created": "2021-01-09 19:10:47",
"created_user_id": "bkQV8I5BRcAVpgod",
"created_by": "Max Smith",
"modified": "2024-05-21 14:19:47",
"modified_user_id": "bkQV8I5BRcAVpgod",
"modified_by": "Max Smith"
}
Example Error Response
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "Your request was successfully processed but there was no data to be returned.",
"details": []
}
}
Create Server Group
Path: /server-groups/create
Method: POST
Authentication: Bearer Token
Request Headers
| Key | Value | Required |
|---|---|---|
Content-Type |
application/json |
required |
Request Parameters
None.
Request Body Parameters
| Key | Data Type | Required | Notes |
|---|---|---|---|
name |
string | required | The name of the server group |
description |
string | optional | Description of the server group |
connection_logging |
boolean | optional | Whether SSH Connection Logging is enabled for servers in this group. When enabled, the Keystash Agent records SSH session authentication events, which are surfaced in the SSH Sessions resource and the app's SSH Sessions view. Requires a Keystash Agent version that supports SSH session logging. Defaults to true if not provided. |
password_auth_enabled |
boolean | required | Whether password authentication is enabled. Note: Cannot be set to true if two_factor_enabled is true. |
two_factor_enabled |
boolean | required | Whether two-factor authentication is enabled. Note: Cannot be set to true if password_auth_enabled is true. |
two_factor_disallow_reuse |
boolean | required | Whether to allow Two Factor codes to be used more than once. This option determines if you are able to use a Two Factor 6 Digit pin more than once in a 30 second window. For example: If you open two SSH connections to the same server in short succession you would be prompted for a Two Factor Authentication 6 digit pin. If you entered in the pin on the first SSH session you would have to wait for a new 6 digit pin to generate before you could login on the second connection. Disabling this option allows you to use the same 6 digit pin two or more times in quick succession. We suggest enabling this for increased security. |
two_factor_allow_unenrolled |
boolean | required | Whether users who have not yet enrolled in Two Factor Authentication are permitted to log in to servers in this group. This setting only takes effect when two_factor_enabled is true. We suggest leaving this disabled so that every user must complete Two Factor Authentication enrolment before they can log in. |
two_factor_window_size |
integer | optional | Allowance for time difference between server and your mobile phone - As Keystash uses the TOTP algorithm it is important to ensure that all servers using SSH Two Factor Authentication have a reliable NTP source. This is so that all your users mobile phones and all the servers have the correct date and time. Large differences (over 2 minutes) can cause issues during SSH Two Factor Authentication. To help combat these issues you can allow for medium (75 seconds) and large (130 seconds) differences between the servers clocks and the mobile phones clocks. Normal is considered the most secure but is the most strict. The available options for this setting are: 1 = Normal, 2 = Medium and 3 = Large. Defaults to 1 (Normal) if not provided. |
two_factor_rate_limit |
integer | optional | The rate limit for two-factor authentication attempts. Available options are: 1,2,3 or 4. 1 = (Off) No rate limiting. 2 = (Permissive) 10 logins every 30 seconds per user account. 3 = (Normal) 3 logins every 30 seconds per user account. 4 = (Restrictive) 1 login every 30 seconds per user account. Defaults to 3 (Normal) if not provided. |
Note
SSH Connection Logging feeds the SSH Sessions resource. To learn more about the feature and how sessions are recorded, see the user-facing Server Groups and SSH Sessions pages.
Example Request Body
{
"name": "My Group",
"description": "My Group of servers",
"connection_logging": true,
"password_auth_enabled": false,
"two_factor_enabled": true,
"two_factor_disallow_reuse": true,
"two_factor_allow_unenrolled": false,
"two_factor_window_size": 3,
"two_factor_rate_limit": 2
}
Example Request
curl --location --request POST 'https://app.keystash.io/api/v1/server-groups/create' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data-raw '{
"name": "My Group",
"description": "My Group of servers",
"connection_logging": true,
"password_auth_enabled": false,
"two_factor_enabled": true,
"two_factor_disallow_reuse": true,
"two_factor_allow_unenrolled": false,
"two_factor_window_size": 3,
"two_factor_rate_limit": 2
}'
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"result": "Server Group was successfully created.",
"id": "BD720EP87kNORRcH"
}
Example Error Response
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "BadArgument",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
{
"field": "name",
"message": "name is a required field and cannot be empty."
}
]
}
}
Set Default Server Group
Path: /server-groups/set-default
Method: POST
Authentication: Bearer Token
Request Headers
| Key | Value | Required |
|---|---|---|
Content-Type |
application/json |
required |
Request Parameters
None.
Request Body Parameters
| Key | Data Type | Required | Notes |
|---|---|---|---|
id |
string | required | The ID of the server group to set as default |
Example Request Body
{
"id": "BD720EP87kNORRcH"
}
Example Request
curl --location --request POST 'https://app.keystash.io/api/v1/server-groups/set-default' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data-raw '{
"id": "BD720EP87kNORRcH"
}'
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"result": "Server Group with ID BD720EP87kNORRcH was successfully updated."
}
Example Error Response
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "Your request was successfully processed but there was no data to be returned.",
"details": []
}
}
Update Server Group
Path: /server-groups/update
Method: PATCH
Authentication: Bearer Token
Request Headers
| Key | Value | Required |
|---|---|---|
Content-Type |
application/json |
required |
Request Parameters
None.
Request Body Parameters
| Key | Data Type | Required | Notes |
|---|---|---|---|
id |
string | required | The ID of the server group to update |
name |
string | optional | The name of the server group |
description |
string | optional | Description of the server group |
connection_logging |
boolean | optional | Whether SSH Connection Logging is enabled for servers in this group. When enabled, the Keystash Agent records SSH session authentication events, which are surfaced in the SSH Sessions resource and the app's SSH Sessions view. Requires a Keystash Agent version that supports SSH session logging. If not provided, the current value is left unchanged. |
password_auth_enabled |
boolean | optional | Whether password authentication is enabled. Note: Cannot be set to true if two_factor_enabled is true. |
two_factor_enabled |
boolean | optional | Whether two-factor authentication is enabled. Note: Cannot be set to true if password_auth_enabled is true. |
two_factor_disallow_reuse |
boolean | optional | Whether to allow Two Factor codes to be used more than once. This option determines if you are able to use a Two Factor 6 Digit pin more than once in a 30 second window. For example: If you open two SSH connections to the same server in short succession you would be prompted for a Two Factor Authentication 6 digit pin. If you entered in the pin on the first SSH session you would have to wait for a new 6 digit pin to generate before you could login on the second connection. Disabling this option allows you to use the same 6 digit pin two or more times in quick succession. We suggest enabling this for increased security. |
two_factor_allow_unenrolled |
boolean | optional | Whether users who have not yet enrolled in Two Factor Authentication are permitted to log in to servers in this group. This setting only takes effect when two_factor_enabled is true. We suggest leaving this disabled so that every user must complete Two Factor Authentication enrolment before they can log in. If not provided, the current value is left unchanged. |
two_factor_window_size |
integer | optional | Allowance for time difference between server and your mobile phone - As Keystash uses the TOTP algorithm it is important to ensure that all servers using SSH Two Factor Authentication have a reliable NTP source. This is so that all your users mobile phones and all the servers have the correct date and time. Large differences (over 2 minutes) can cause issues during SSH Two Factor Authentication. To help combat these issues you can allow for medium (75 seconds) and large (130 seconds) differences between the servers clocks and the mobile phones clocks. Normal is considered the most secure but is the most strict. The available options for this setting are: 1 = Normal, 2 = Medium and 3 = Large. Defaults to 1 (Normal) if not provided. |
two_factor_rate_limit |
integer | optional | The rate limit for two-factor authentication attempts. Available options are: 1,2,3 or 4. 1 = (Off) No rate limiting. 2 = (Permissive) 10 logins every 30 seconds per user account. 3 = (Normal) 3 logins every 30 seconds per user account. 4 = (Restrictive) 1 login every 30 seconds per user account. Defaults to 3 (Normal) if not provided. |
Example Request Body
{
"id": "BD720EP87kNORRcH",
"name": "API Test Group",
"description": "New description.",
"connection_logging": true,
"two_factor_window_size": 1,
"two_factor_rate_limit": 1
}
Example Request
curl --location --request PATCH 'https://app.keystash.io/api/v1/server-groups/update' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data-raw '{
"id": "BD720EP87kNORRcH",
"name": "API Test Group",
"description": "New description.",
"connection_logging": true,
"two_factor_window_size": 1,
"two_factor_rate_limit": 1
}'
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"result": "Server Group with ID BD720EP87kNORRcH was successfully updated."
}
Example Error Response
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "Your request was successfully processed but there was no data to be returned.",
"details": []
}
}
Delete Server Group
Path: /server-groups/delete
Method: DELETE
Authentication: Bearer Token
Request Headers
| Key | Value | Required |
|---|---|---|
Accept-Encoding |
gzip | optional |
Request Parameters
| Key | Data Type | Required | Notes |
|---|---|---|---|
id |
string | required | The ID of the server group to delete |
Request Body
None.
Example Request
curl --location --request DELETE 'https://app.keystash.io/api/v1/server-groups/delete?id=BD720EP87kNORRcH' \
--header 'Authorization: Bearer <token>'
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"result": "Server Group with ID BD720EP87kNORRcH was successfully deleted."
}
Example Error Response
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "Your request was successfully processed but there was no data to be returned.",
"details": []
}
}
List Users in Server Group
This endpoint returns every user in your company, each carrying the permission level they hold on the named Server Group. A user with no access to the group appears with a permission_level of Disabled rather than being left out, so the list is a permissions view of the group rather than a membership list.
Note
Because the response covers every user in your company, a company with more than 250 users spans several pages. To check one particular user, narrow the request with ?user_ids[]=<id> rather than searching through the pages.
Path: /server-groups/list-users
Method: GET
Authentication: Bearer Token
Request Headers
| Key | Value | Required |
|---|---|---|
Accept-Encoding |
gzip | optional |
Request Parameters
Every parameter other than id is optional. Combine as many as you need and they are all applied together.
| Key | Data Type | Required | Notes |
|---|---|---|---|
id |
string | required | The id of the Server Group whose users are listed. 1–16 alphanumeric characters. A missing or malformed value returns a 400 BadArgument, and a well-formed but unknown value returns a 404 NotFound. |
user_ids |
array of string | optional | One or more user id values, being the user_id field in a response. Each is 1–16 alphanumeric characters. |
firstname |
string | optional | 1–255 characters. Matches any user whose first name contains this value. |
lastname |
string | optional | 1–255 characters. Matches any user whose last name contains this value. |
email |
string | optional | 1–255 characters. Matches any user whose email contains this value. |
server_username |
string | optional | 1–255 characters. Matches any user whose Server Username contains this value. |
permission_level |
array of string | optional | One or more of Disabled, User, Root. Case-insensitive. Matches the effective permission level shown in the response, after User Group inheritance has been resolved. |
override_groups |
boolean | optional | true, false, 1 or 0. Filters on whether the user's settings override those inherited from their User Groups. |
permission_level_inherited |
boolean | optional | true, false, 1 or 0. Filters on whether the permission level shown is inherited from a User Group. |
linux_groups_inherited |
boolean | optional | true, false, 1 or 0. Filters on whether the Linux Groups shown are inherited from a User Group. |
limit |
integer | optional | Rows to return. Defaults to 250, which is also the maximum; a larger value is reduced to 250. |
offset |
integer | optional | Row offset for paging. Defaults to 0. |
Note
permission_level filters on the level the user effectively has, which is the level in the response. A user who is Root through a User Group matches ?permission_level[]=Root even though the permission was never assigned to them directly. You can read more about how this is resolved here.
Note
A parameter that is not recognised, or a value that fails its rule, returns a 400 BadArgument naming every parameter at fault. See Filtering Lists for the full rules, and Paging Through Lists for the X-Total-Count, X-Limit and X-Offset headers.
Request Body
None.
Example Request
curl --location --request GET 'https://app.keystash.io/api/v1/server-groups/list-users?id=BD720EP87kNORRcH' \
--header 'Authorization: Bearer <token>'
Narrowing the list to the users who hold root access on the group, 100 rows at a time:
curl --location --request GET 'https://app.keystash.io/api/v1/server-groups/list-users?id=BD720EP87kNORRcH&permission_level[]=Root&limit=100' \
--header 'Authorization: Bearer <token>'
Response Fields
A successful response is a JSON array of user objects, returned in last name, then first name order.
| Field | Data Type | Description |
|---|---|---|
user_id |
string | The unique ID of the user |
firstname |
string | The user's first name |
lastname |
string | The user's last name |
server_username |
string | The username used on servers for this user |
email |
string | The user's email address |
permission_level |
string | The effective permission level for this user in the server group. Possible values: "Root", "User", "Disabled" |
override_groups |
boolean | Indicates whether the user has individual permission settings that override inherited settings from User Groups |
permission_level_inherited |
boolean | Indicates whether the user's permission level is inherited from User Groups. When true and override_groups is false, the permission level comes from User Group membership |
linux_groups_inherited |
boolean | Indicates whether the user's Linux groups are inherited from User Groups. When true and override_groups is false, the Linux groups come from User Group membership |
linux_groups |
array | Array of Linux group objects assigned to the user. Each object contains id (the Linux group's ID) and name (the Linux group's name) |
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Total-Count: 3
X-Limit: 250
X-Offset: 0
[
{
"user_id": "bkQV8I5BRcAVpgod",
"firstname": "Max",
"lastname": "Smith",
"server_username": "maxsmith",
"email": "max.smith@example.org",
"permission_level": "Root",
"override_groups": false,
"permission_level_inherited": false,
"linux_groups_inherited": false,
"linux_groups": [
{
"id": "Gfz5m9mGuIp6ByPz",
"name": "developers"
},
{
"id": "rzbSZtL2zI0oA16V",
"name": "admins"
}
]
},
{
"user_id": "t2er3Mo68eFWMbVk",
"firstname": "Anne",
"lastname": "Teak",
"server_username": "anneteak",
"email": "anne.teak@example.org",
"permission_level": "User",
"override_groups": false,
"permission_level_inherited": true,
"linux_groups_inherited": true,
"linux_groups": [
{
"id": "Gfz5m9mGuIp6ByPz",
"name": "developers"
}
]
},
{
"user_id": "ZaPkEfpPIlhKv3eO",
"firstname": "Perry",
"lastname": "Scope",
"server_username": "perryscope",
"email": "perry.scope@example.org",
"permission_level": "Disabled",
"override_groups": true,
"permission_level_inherited": false,
"linux_groups_inherited": false,
"linux_groups": []
}
]
Example Error Response
Missing or Malformed ID (400 Bad Request)
The id of the Server Group is required, so a request without it is rejected before anything is read. A value that is present but is not a 1–16 character alphanumeric id is reported the same way, with a received field echoing the value you sent.
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "BadArgument",
"message": "One or more query parameters were invalid.",
"details": [
{
"field": "id",
"message": "Required. The id of the Server Group whose users are being listed."
}
]
}
}
Server Group Not Found (404 Not Found)
A 404 here means the Server Group id is unknown or belongs to another company. A Server Group that has nothing to list returns a 200 OK with an empty array ([]), as does an offset past the end of the results.
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "Your request was successfully processed but there was no data to be returned.",
"details": []
}
}
Update User in Server Group
Path: /server-groups/update-user
Method: PATCH
Authentication: Bearer Token
Request Headers
| Key | Value | Required |
|---|---|---|
Content-Type |
application/json |
required |
Request Parameters
None
Request Body Parameters
| Key | Data Type | Required | Notes |
|---|---|---|---|
server_group_id |
string | required | The ID of the server group |
user_id |
string | required | The ID of the user to update |
permission_level |
string | required | The new permission level for the user. Options are "Disabled", "User" and "Root". |
override_groups |
boolean | optional | Whether to override inherited settings from User Groups. When true, the user's individual permission and Linux group settings take precedence over those inherited from User Groups. When false or not provided, settings are inherited from User Groups. Defaults to false. |
linux_group_ids |
array | optional | Array of Linux group IDs to assign to the user in this server group. Each element should be a string containing a valid Linux group ID. If not provided, existing Linux group assignments remain unchanged. |
linux_groups |
array | optional | Array of Linux group objects with IDs to assign to the user in this server group. Each element should be an object containing a valid Linux group ID. If not provided, existing Linux group assignments remain unchanged. |
| Note | You should only provide linux_group_ids OR linux_groups, never both. The system will always prioritise and use linux_group_ids over linux_groups. linux_groups is provided as a convenience field allowing users to copy linux_groups from the response provided by /server-groups/list-user-groups API endpoint. |
Example Request Body
{
"server_group_id": "BD720EP87kNORRcH",
"user_id": "bkQV8I5BRcAVpgod",
"permission_level": "User",
"override_groups": true,
"linux_group_ids": ["Gfz5m9mGuIp6ByPz", "rzbSZtL2zI0oA16V"],
"linux_groups": [{"id": "Gfz5m9mGuIp6ByPz"}, {"id": "rzbSZtL2zI0oA16V"}]
}
Example Request
curl --location --request PATCH 'https://app.keystash.io/api/v1/server-groups/update-user' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data-raw '{
"server_group_id": "BD720EP87kNORRcH",
"user_id": "bkQV8I5BRcAVpgod",
"permission_level": "User",
"override_groups": true,
"linux_group_ids": ["Gfz5m9mGuIp6ByPz", "rzbSZtL2zI0oA16V"]
}'
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"result": "Server Group with ID BD720EP87kNORRcH was successfully updated."
}
Example Error Response
Missing Required Parameters (400 Bad Request)
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "BadArgument",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
"The following required parameters are missing from your request: server_group_id, user_id"
]
}
}
Invalid Permission Level (400 Bad Request)
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "BadArgument",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
"Invalid permission level provided. Valid options are: Root, User, Disabled"
]
}
}
User Not Found (404 Not Found)
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
"Could not find a User for the User ID provided."
]
}
}
Server Group Not Found (404 Not Found)
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
"Could not find a Server Group for the Server Group ID provided."
]
}
}
Linux Groups Not Found (404 Not Found)
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
"Could not find Linux Groups with IDs: xyz123abc456"
]
}
}
Database Save Error (500 Internal Server Error)
HTTP/1.1 500 Internal Server Error
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "DataSaveError",
"message": "There was a system problem while saving data to the database.",
"details": []
}
}
List User Groups in Server Group
This endpoint returns the User Groups that hold something on the named Server Group, being a permission, a Linux Group, or both. A User Group with neither is not listed. To see every User Group in your company, use List User Groups and match the results yourself.
Path: /server-groups/list-user-groups
Method: GET
Authentication: Bearer Token
Request Headers
| Key | Value | Required |
|---|---|---|
Accept-Encoding |
gzip | optional |
Request Parameters
Every parameter other than id is optional. Combine as many as you need and they are all applied together.
| Key | Data Type | Required | Notes |
|---|---|---|---|
id |
string | required | The id of the Server Group whose User Groups are listed. 1–16 alphanumeric characters. A missing or malformed value returns a 400 BadArgument, and a well-formed but unknown value returns a 404 NotFound. |
user_group_ids |
array of string | optional | One or more User Group id values, being the user_group_id field in a response. Each is 1–16 alphanumeric characters. |
name |
string | optional | 1–255 characters. Matches any User Group whose name contains this value. |
description |
string | optional | 1–255 characters. Matches any User Group whose description contains this value. |
permission_level |
array of string | optional | One or more of Unset, Disabled, User, Root. Case-insensitive. Unset matches a User Group that appears in this list on the strength of a Linux Group assignment alone, holding no permission level on the group. |
limit |
integer | optional | Rows to return. Defaults to 250, which is also the maximum; a larger value is reduced to 250. |
offset |
integer | optional | Row offset for paging. Defaults to 0. |
Note
id names the Server Group you are listing against, and is required. user_group_ids filters the User Groups that come back. Sending ids here returns a 400 BadArgument.
Note
A parameter that is not recognised, or a value that fails its rule, returns a 400 BadArgument naming every parameter at fault. See Filtering Lists for the full rules, and Paging Through Lists for the X-Total-Count, X-Limit and X-Offset headers.
Request Body
None.
Example Request
curl --location --request GET 'https://app.keystash.io/api/v1/server-groups/list-user-groups?id=BD720EP87kNORRcH' \
--header 'Authorization: Bearer <token>'
Narrowing the list to the User Groups that grant access to the group:
curl --location --request GET 'https://app.keystash.io/api/v1/server-groups/list-user-groups?id=BD720EP87kNORRcH&permission_level[]=Root&permission_level[]=User' \
--header 'Authorization: Bearer <token>'
Response Fields
A successful response is a JSON array of User Group objects, returned in name order.
| Field | Data Type | Description |
|---|---|---|
user_group_id |
string | The unique ID of the user group |
name |
string | The user group's name |
description |
string | The user group's description |
permission_level |
string | The permission level this User Group holds on the Server Group. One of Root, User, Disabled, or Unset when the User Group appears here on the strength of a Linux Group assignment alone |
user_count |
integer | The number of users in the user group |
linux_groups |
array | Array of Linux group objects assigned to the user group in this server group. Each object contains id (the Linux group's ID) and name (the Linux group's name) |
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Total-Count: 3
X-Limit: 250
X-Offset: 0
[
{
"user_group_id": "p3Km8NxLtYqR9wZd",
"name": "Development Team",
"description": "Development team user group",
"permission_level": "Root",
"user_count": 5,
"linux_groups": [
{
"id": "Gfz5m9mGuIp6ByPz",
"name": "developers"
},
{
"id": "rzbSZtL2zI0oA16V",
"name": "admins"
}
]
},
{
"user_group_id": "v7QxRm2NhPzF4jLk",
"name": "Operations Team",
"description": "Operations and infrastructure team",
"permission_level": "User",
"user_count": 3,
"linux_groups": [
{
"id": "Gfz5m9mGuIp6ByPz",
"name": "developers"
}
]
},
{
"user_group_id": "n9TwYp5MkBvD8xRh",
"name": "Contractors",
"description": "",
"permission_level": "Disabled",
"user_count": 2,
"linux_groups": []
}
]
Example Error Response
Missing or Malformed ID (400 Bad Request)
The id of the Server Group is required, so a request without it is rejected before anything is read. A value that is present but is not a 1–16 character alphanumeric id is reported the same way, with a received field echoing the value you sent.
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "BadArgument",
"message": "One or more query parameters were invalid.",
"details": [
{
"field": "id",
"message": "Required. The id of the Server Group whose User Groups are being listed."
}
]
}
}
Server Group Not Found (404 Not Found)
A 404 here means the Server Group id is unknown or belongs to another company. A Server Group with no User Groups holding a permission or a Linux Group on it returns a 200 OK with an empty array ([]), as does an offset past the end of the results.
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "Your request was successfully processed but there was no data to be returned.",
"details": []
}
}
Update User Group in Server Group
Path: /server-groups/update-user-group
Method: PATCH
Authentication: Bearer Token
Request Headers
| Key | Value | Required |
|---|---|---|
Content-Type |
application/json |
required |
Request Parameters
None
Request Body Parameters
| Key | Data Type | Required | Notes |
|---|---|---|---|
server_group_id |
string | required | The ID of the server group |
user_group_id |
string | required | The ID of the user group to update |
permission_level |
string | required | The permission level for the user group. Options are "Disabled", "User", "Root", or "Unset". Setting to "Unset" removes the user group's permissions from the server group. Note: Cannot set to "Unset" if the user group does not currently have permissions for this server group. |
linux_group_ids |
array | optional | Array of Linux group IDs to assign to the user group in this server group. Each element should be a string containing a valid Linux group ID. If not provided, existing Linux group assignments remain unchanged. |
linux_groups |
array | optional | Array of Linux group objects with IDs to assign to the user group in this server group. Each element should be an object containing a valid Linux group ID. If not provided, existing Linux group assignments remain unchanged. |
| Note | You should only provide linux_group_ids OR linux_groups, never both. The system will always prioritise and use linux_group_ids over linux_groups. linux_groups is provided as a convenience field allowing users to copy linux_groups from the response provided by /server-groups/list-users API endpoint. |
Example Request Body
{
"server_group_id": "BD720EP87kNORRcH",
"user_group_id": "p3Km8NxLtYqR9wZd",
"permission_level": "Root",
"linux_group_ids": ["Gfz5m9mGuIp6ByPz", "rzbSZtL2zI0oA16V"]
}
Example Request
curl --location --request PATCH 'https://app.keystash.io/api/v1/server-groups/update-user-group' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token>' \
--data-raw '{
"server_group_id": "BD720EP87kNORRcH",
"user_group_id": "p3Km8NxLtYqR9wZd",
"permission_level": "Root",
"linux_group_ids": ["Gfz5m9mGuIp6ByPz", "rzbSZtL2zI0oA16V"]
}'
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"result": "Server Group with ID BD720EP87kNORRcH was successfully updated."
}
Example Error Response
Missing Required Parameters (400 Bad Request)
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "BadArgument",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
"The following required parameters are missing from your request: server_group_id, user_group_id"
]
}
}
Invalid Permission Level (400 Bad Request)
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "BadArgument",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
{
"field": "permission_level",
"validation": "value",
"message": "The permission_level must be a string set to 'Disabled', 'User', 'Root' or 'Unset'."
}
]
}
}
Cannot Unset Non-Existent Permission (400 Bad Request)
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "BadArgument",
"message": "Cannot unset a permission that does not exist. The User Group does not currently have any permissions for this Server Group.",
"details": []
}
}
User Group Not Found (404 Not Found)
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
"Could not find a User Group for the User Group ID provided."
]
}
}
Server Group Not Found (404 Not Found)
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
"Could not find a Server Group for the Server Group ID provided."
]
}
}
Linux Groups Not Found (404 Not Found)
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "NotFound",
"message": "There was a problem with one or more arguments in your request. Please check your request and resubmit.",
"details": [
"Could not find Linux Groups with IDs: xyz123abc456"
]
}
}
Database Save Error (500 Internal Server Error)
HTTP/1.1 500 Internal Server Error
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "DataSaveError",
"message": "There was a system problem while saving data to the database.",
"details": []
}
}