Skip to content

Change the SSH keys that can log in to a VPS

PATCH /api/v2/vps/{id}/ssh-access

Removes chosen key lines from ~/.ssh/authorized_keys on the running VPS and adds saved account keys to it. Other lines stay as they are, options included. Read GET /api/v2/vps/{id}/ssh-access first. Send its revision and the entries[].id values to remove. If the file changed since that read, nothing is written and the call returns 409 ssh_access_changed. The file is read back after the write. The response is the new list with lastOperation. Removing every key needs confirmRemoveAll: true. With no keys left, the login user cannot log in with an SSH key.

Authentication: An API key with the scope write:vm. About keys and scopes

Request

Path parameters

idstringrequired
The VPS ID (vps_…).

Body

revisionstringrequired
revision from the latest GET.
removeEntryIdsarray of stringrequired
entries[].id values to remove. Send [] to remove nothing.
addSshKeyIdsarray of stringrequired
Saved SSH key IDs (ssh_…) to add. A key that is already in the file is not added twice. Send [] to add nothing.
confirmRemoveAllboolean
Set to true when the change leaves no keys in the file. Default false.

Example

PATCH /api/v2/vps/{id}/ssh-access
curl -X PATCH "https://cloud.hostup.se/api/v2/vps/vps_01hxa3b4c5d6e7f8g9h0j1k2m3/ssh-access" \
-H "Authorization: Bearer $HOSTUP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"revision": "9b74c9897bac770ffc029102a200c5de6e2c7e1c4f2a3b8d0e5f6a7b8c9d0e1f",
"removeEntryIds": [
"ak_3f9a1c7e5b2d8a4c6e0f1b3d5a"
],
"addSshKeyIds": [
"ssh_01hxa3b4c5d6e7f8g9h0j1k2m3"
]
}'

Responses

200 The change is written and read back. Same shape as the GET, plus lastOperation.

Response 200
{
"available": true,
"unavailableReason": null,
"unavailableMessage": null,
"loginUser": "root",
"checkedAt": "2026-08-13T10:01:00.000Z",
"revision": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
"entries": [
{
"id": "ak_7c9e1f3a5b2d8a4c6e0f1b3d5a",
"keyType": "ssh-ed25519",
"fingerprint": "SHA256:exampleFingerprint",
"comment": "alex@laptop",
"restricted": false,
"restrictions": [],
"savedKeyId": "ssh_01hxa3b4c5d6e7f8g9h0j1k2m3",
"savedKeyName": "Laptop"
}
],
"savedKeys": [
{
"id": "ssh_01hxa3b4c5d6e7f8g9h0j1k2m3",
"name": "Laptop",
"fingerprint": "SHA256:exampleFingerprint",
"active": true,
"activeEntryIds": [
"ak_7c9e1f3a5b2d8a4c6e0f1b3d5a"
]
}
],
"lastOperation": {
"added": 1,
"removed": 1,
"verified": true,
"metadataSynced": true
}
}
Response fields
availableboolean
Always true after a change. One of true.
unavailableReasonnull
Always null after a change.
unavailableMessagenull
Always null after a change.
loginUserstring
The user whose ~/.ssh/authorized_keys was read. The VPS’s default login user, usually root.
checkedAtstring
When the file was read.
revisionstring
The new version of the file. Send it with the next PATCH.
entriesarray of object
Every public key line in the file, including keys added inside the VPS.
idstring
ID of this line in the file. It changes when the line or its position changes. Use it in removeEntryIds.
keyTypestring
Key algorithm.
fingerprintstring
SHA256 fingerprint of the public key.
commentstring or null
Comment at the end of the key line.
restrictedboolean
True when the line has OpenSSH options that limit the key.
restrictionsarray of string
The options on the line. forced_command is command=, source_restricted is from=, expires is expiry-time=, restricted is restrict. custom_options covers any other option. The values of the options are not returned.
savedKeyIdstring or null
The saved SSH key on your account with the same public key. Null when the key is not saved on the account.
savedKeyNamestring or null
Name of that saved key.
savedKeysarray of object
The SSH keys saved on your account and whether each one is in the file.
idstring
Saved SSH key ID. Use it in addSshKeyIds.
namestring
Name of the saved key.
fingerprintstring or null
SHA256 fingerprint of the key.
activeboolean
True when the key is in the file now.
activeEntryIdsarray of string
The entries[].id values that hold this key.
lastOperationobject
What this change did.
addedinteger
Number of saved key IDs sent in addSshKeyIds. At least 0.
removedinteger
Number of lines removed. At least 0.
verifiedboolean
Always true. The file was read back and matches the change. One of true.
metadataSyncedboolean
True when the VPS’s cloud-init key list was also set to the saved keys now in the file. A rebuild then installs the same keys.

Errors

Errors are Problem Details with a stable code. Branch on the code, not on the text.

400Invalid body. code is invalid_request. It is confirmation_required when the change would leave no keys and confirmRemoveAll is not true.
401Unauthorized. Authentication is required.
403Forbidden. The caller lacks a required scope or does not own the resource.
404Not found. The resource does not exist or is not owned by the caller; code is vps_not_found.
409The change was not made or could not be read back. code is ssh_access_unavailable (the file cannot be read, for example the VPS is stopped), ssh_access_changed (the file changed since your GET: read it again), ssh_access_update_failed (the write failed and the old file is kept) or ssh_access_verification_failed (the write ran but could not be read back: check access through the console).
429Rate limited. Retry after the limit resets. 429 responses include Retry-After seconds plus X-RateLimit-* headers.
500Internal error. Retry later or contact support if the issue persists.