curl --request POST \
--url https://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"datacenter": "<string>",
"gpu_type": "<string>",
"force": false
}
'import requests
url = "https://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware"
payload = {
"datacenter": "<string>",
"gpu_type": "<string>",
"force": False
}
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({datacenter: '<string>', gpu_type: '<string>', force: false})
};
fetch('https://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware', 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://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware",
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([
'datacenter' => '<string>',
'gpu_type' => '<string>',
'force' => false
]),
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://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware"
payload := strings.NewReader("{\n \"datacenter\": \"<string>\",\n \"gpu_type\": \"<string>\",\n \"force\": false\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://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"datacenter\": \"<string>\",\n \"gpu_type\": \"<string>\",\n \"force\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware")
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 \"datacenter\": \"<string>\",\n \"gpu_type\": \"<string>\",\n \"force\": false\n}"
response = http.request(request)
puts response.read_body{
"key": "<string>",
"name": "<string>",
"type": "<string>",
"gpu_type": "<string>",
"enabled": true,
"status": "<string>",
"est_hourly_cost": 123,
"capacity_per_pod": 123,
"datacenter": "<string>",
"live_url": "<string>",
"est_hourly_cost_source": "registry_estimate",
"error": "<string>",
"desired_count": 1,
"auto_scale": false,
"pods": [],
"canary": {
"version": "<string>",
"percent": 123,
"pods": 123,
"healthy": 123
},
"workers_min": 123,
"workers_max": 123,
"co_hosted_on": "<string>",
"pod_image": "<string>",
"blockers": [],
"bake": {
"status": "<string>",
"image": "<string>",
"built_at": "<string>",
"added": [],
"removed": [],
"changed": [],
"summary": "<string>"
},
"pinned_datacenter": "<string>",
"pinned_gpu_type": "<string>",
"pinned_gpu_forced": false,
"hardware_source": "auto",
"hardware_pinned_at": "2023-11-07T05:31:56Z",
"hardware_drift": "<string>",
"hardware_warning": "<string>",
"direct_url": "<string>",
"direct_url_in_use": false
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Set Plane Hardware
Pin (or un-pin) this plane’s REGION and CARD — validated against live stock before anything is written.
THE REFUSAL IS THE FEATURE. An impossible combination comes back 422 with
the binding constraint, the reason WITH ITS NUMBERS and the same offer table
the picker renders, so the operator learns why on the screen they are
already looking at instead of from a launch that fails an hour later. Send
it again with force to save it anyway: unlike the env default, a forced
pin still reads the market and still carries the contradiction into the
launch log.
force ALSO covers the market being unreadable — a 503 with no force,
and with it the pin is saved UNVERIFIED with a warning that says so in those
words. The two forced states are kept distinguishable on the wire because
they are different facts: “we asked and the answer was no” carries a reason
with numbers, “we could not ask” carries nothing, and the operator debugging
a dead pod later has only that sentence to tell them apart.
Both nulls clear the pin. That is never refused — clearing only ever WIDENS the requirement, so validating it could only refuse a state that already exists, and an operator must always be able to undo.
RUNNING PODS ARE NOT TOUCHED. This applies to the next launch; the response
carries hardware_drift while the fleet is still on the old card. A
rolling restart here would drop live calls.
curl --request POST \
--url https://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"datacenter": "<string>",
"gpu_type": "<string>",
"force": false
}
'import requests
url = "https://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware"
payload = {
"datacenter": "<string>",
"gpu_type": "<string>",
"force": False
}
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({datacenter: '<string>', gpu_type: '<string>', force: false})
};
fetch('https://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware', 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://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware",
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([
'datacenter' => '<string>',
'gpu_type' => '<string>',
'force' => false
]),
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://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware"
payload := strings.NewReader("{\n \"datacenter\": \"<string>\",\n \"gpu_type\": \"<string>\",\n \"force\": false\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://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"datacenter\": \"<string>\",\n \"gpu_type\": \"<string>\",\n \"force\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.peachdeskai.com/api/v1/sa/gpu/planes/{key}/hardware")
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 \"datacenter\": \"<string>\",\n \"gpu_type\": \"<string>\",\n \"force\": false\n}"
response = http.request(request)
puts response.read_body{
"key": "<string>",
"name": "<string>",
"type": "<string>",
"gpu_type": "<string>",
"enabled": true,
"status": "<string>",
"est_hourly_cost": 123,
"capacity_per_pod": 123,
"datacenter": "<string>",
"live_url": "<string>",
"est_hourly_cost_source": "registry_estimate",
"error": "<string>",
"desired_count": 1,
"auto_scale": false,
"pods": [],
"canary": {
"version": "<string>",
"percent": 123,
"pods": 123,
"healthy": 123
},
"workers_min": 123,
"workers_max": 123,
"co_hosted_on": "<string>",
"pod_image": "<string>",
"blockers": [],
"bake": {
"status": "<string>",
"image": "<string>",
"built_at": "<string>",
"added": [],
"removed": [],
"changed": [],
"summary": "<string>"
},
"pinned_datacenter": "<string>",
"pinned_gpu_type": "<string>",
"pinned_gpu_forced": false,
"hardware_source": "auto",
"hardware_pinned_at": "2023-11-07T05:31:56Z",
"hardware_drift": "<string>",
"hardware_warning": "<string>",
"direct_url": "<string>",
"direct_url_in_use": false
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Authorizations
Interactive user session: the login JWT, sent as Authorization: Bearer <token>.
Path Parameters
Body
Response
Successful Response
One plane's card for the SA GPU screen.
Show child attributes
Show child attributes
The plane's active canary (Phase H6), or absent when none is configured.
version is the OPERATOR'S label tying the rollout to the model/adapter
they just trained (it must match the model_version the canary pod was
launched with); pods/healthy count the plane's pods at that
version.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
The pod's baked-store freshness verdict
(services/voice-engine/scripts/bake_manifest.py).
A baked image pins its model set at BUILD time and the warm-store skip
deliberately declines to re-sync it, so a pod can serve last week's weights
indefinitely with no symptom but behaviour. status is fresh |
stale | unknown (the bucket could not be listed — never guessed).
Show child attributes
Show child attributes
Whether live traffic is actually being ROUTED at the direct address (VOICE_POD_DIRECT_URL). Knowing the address and using it are different facts, and this one is OFF by default on purpose. A RunPod direct TCP port is PLAINTEXT — the engine terminates no TLS, so the hop is plain HTTP across the public internet — and the bearer sent on it is the RunPod ACCOUNT api key, which creates and terminates pods and whose GET /v1/pods returns every pod's env including the workers' S3 credentials. Turning this on leaks that key, and the call audio and transcripts beside it, to any observer on the path, ~3 times per conversational turn. PREREQUISITES before it may carry live traffic: (1) the hop is encrypted — the engine terminating TLS on the direct port, or a mutually-authenticated tunnel (WireGuard/Tailscale) between the api task and the pod; and (2) the bearer is a NARROW, pod-scoped token instead of the account key. Neither is in place today. Read pod_pool.prefer_direct_pod_urls before flipping it; use pod_rtt_probe compare to measure without routing anything.

