curl --request POST \
--url https://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"service_account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"name": "ci-pipeline-key"
}
'import requests
url = "https://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys"
payload = {
"service_account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"name": "ci-pipeline-key"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
service_account_id: 'c3d4e5f6-a7b8-9012-cdef-123456789012',
name: 'ci-pipeline-key'
})
};
fetch('https://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys', 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://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'service_account_id' => 'c3d4e5f6-a7b8-9012-cdef-123456789012',
'name' => 'ci-pipeline-key'
]),
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://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys"
payload := strings.NewReader("{\n \"service_account_id\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\",\n \"name\": \"ci-pipeline-key\"\n}")
req, _ := http.NewRequest("POST", 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.post("https://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"service_account_id\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\",\n \"name\": \"ci-pipeline-key\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"service_account_id\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\",\n \"name\": \"ci-pipeline-key\"\n}"
response = http.request(request)
puts response.read_body{
"virtual_key_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"key": "REDACTED-FULL-KEY-SHOWN-ONCE",
"last_four": "x7Qa",
"name": "ci-pipeline-key",
"key_type": "service_account",
"user_id": null,
"service_account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"workspace_id": "f6a7b8c9-d0e1-2345-fabc-456789012345",
"project_id": "a7b8c9d0-e1f2-3456-abcd-567890123456",
"status": "active",
"created_at": "2026-10-30T09:00:00Z",
"created_by": "00000000-0000-0000-0000-000000000001",
"revoked_at": null,
"revoked_by": null
}Create Virtual Key
Issue a virtual key for a project to a user or a service account. Provide exactly one of user_id or service_account_id. The user or service account must exist, be a direct member of the workspace, and be active. Each user or service account can hold one virtual key per project: a second request returns 409 with the existing key’s virtual_key_id until that key is revoked. Use Get Virtual Key to inspect the existing key. A disabled key counts toward this limit; a revoked key does not, so a script can safely be re-run. The response contains the full key secret in key. The secret is returned only once and cannot be retrieved again, so store it securely.
curl --request POST \
--url https://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"service_account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"name": "ci-pipeline-key"
}
'import requests
url = "https://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys"
payload = {
"service_account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"name": "ci-pipeline-key"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
service_account_id: 'c3d4e5f6-a7b8-9012-cdef-123456789012',
name: 'ci-pipeline-key'
})
};
fetch('https://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys', 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://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'service_account_id' => 'c3d4e5f6-a7b8-9012-cdef-123456789012',
'name' => 'ci-pipeline-key'
]),
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://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys"
payload := strings.NewReader("{\n \"service_account_id\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\",\n \"name\": \"ci-pipeline-key\"\n}")
req, _ := http.NewRequest("POST", 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.post("https://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"service_account_id\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\",\n \"name\": \"ci-pipeline-key\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://cloud.cdata.com/api/v1/admin/workspaces/{workspace_id}/projects/{project_id}/virtual-keys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"service_account_id\": \"c3d4e5f6-a7b8-9012-cdef-123456789012\",\n \"name\": \"ci-pipeline-key\"\n}"
response = http.request(request)
puts response.read_body{
"virtual_key_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"key": "REDACTED-FULL-KEY-SHOWN-ONCE",
"last_four": "x7Qa",
"name": "ci-pipeline-key",
"key_type": "service_account",
"user_id": null,
"service_account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"workspace_id": "f6a7b8c9-d0e1-2345-fabc-456789012345",
"project_id": "a7b8c9d0-e1f2-3456-abcd-567890123456",
"status": "active",
"created_at": "2026-10-30T09:00:00Z",
"created_by": "00000000-0000-0000-0000-000000000001",
"revoked_at": null,
"revoked_by": null
}Authorizations
The access token received from the authorization server in the OAuth 2.0 flow.
Path Parameters
Workspace identifier (UUID).
Project identifier (UUID).
Body
Response
Created
Virtual key identifier.
The last four characters of the virtual key. Use it to identify a key. The full secret is never returned after creation.
Display name of the virtual key.
The type of identity the key is issued to.
user, service_account The user the key is issued to. null when key_type is service_account.
The service account the key is issued to. null when key_type is user.
The workspace the key belongs to.
The project the key is issued for.
Current state of the key. Revoked is permanent.
active, disabled, revoked ISO 8601 UTC.
ID of the caller that created the key.
ISO 8601 UTC. null unless the key is revoked.
ID of the caller that revoked the key. null unless the key is revoked.
The full virtual key secret. Returned only in the create response and cannot be retrieved again.
Was this page helpful?