---
title: "Get a VM with its GPU/node/template info and price"
method: GET
path: "/v1/vms/{id}/detail"
tags: ["VMs"]
---

# Get a VM with its GPU/node/template info and price

`GET /v1/vms/{id}/detail`

## Path parameters

- `id` string, required

## Response `200`

The VM detail

- VmDetail
  - `capabilityTier` string — compute-fabric capability tier (e.g. "pod"); empty for a plain VM
  - `computeClass` string — compute-fabric purchase option (on_demand; pods created before the rename carry the legacy reserved or interruptible values); empty for a plain VM
  - `containerPort` integer
  - `createdAt` string, required
  - `diskSizeGb` integer, required
  - `diskTotalBytes` integer
  - `diskUsedBytes` integer
  - `endpointUrl` string
  - `gpuCount` integer, required
  - `gpuInfo` VmGpuInfo
    - `name` string, required
    - `pricePerHourCents` integer — current catalog per-GPU-hour rate for this model/tier (informational; the billed rate is VmDetail.pricePerHourCents)
    - `vramGb` integer, required
  - `gpuModelId` string
  - `healthy` boolean, required
  - `hostDiskFreeGb` integer — pods only: free disk on the pod's host node, shared across the pods on that node. Pods have no per-pod quota, and pod storage does not persist across terminate. Absent when the node reports no live disk signal.
  - `hostDiskTotalGb` integer — pods only: total disk on the pod's host node, shared across the pods on that node. Pods have no per-pod quota, and pod storage does not persist across terminate. Absent when the node reports no live disk signal.
  - `id` string, required
  - `imageUrl` string
  - `internalIp` string
  - `name` string, required
  - `nodeId` string
  - `nodeInfo` VmNodeInfo
    - `hostname` string, required
    - `location` string
  - `nonBillable` boolean — This VM's usage is recorded but never charged: a provider org consuming GPUs on a node it owns under its own reservation. pricePerHourCents still reports the real rate (the measurement is kept, the charge is waived) so a client showing a rate MUST also show this or it will display a bill that never arrives.
  - `organizationId` string, required
  - `osType` string
  - `persistentDiskPath` string
  - `pricePerHourCents` integer — bundled hourly rate. When the VM has an open usage session this is the rate LOCKED at session open (what settlement charges); otherwise the rate a session WOULD lock: the fabric admission snapshot for a pod, else the current catalog rate for the VM's shape.
  - `provisioningStage` string
  - `public` boolean — true = open endpoint (no data-plane auth); false = require an org API key
  - `rdpPassword` string
  - `rdpPort` integer
  - `resourceSize` string, required
  - `serviceType` string — managed-service tag; empty for a plain VM
  - `sshCommand` string — ready-to-paste ssh command (ssh <handle>@<host>)
  - `sshHandle` string — RunPod-style SSH handle (first label of endpointUrl); used as the SSH username
  - `sshHost` string — data-plane SSH gateway host, e.g. ssh.run.beta.openrelay.inc
  - `sshPort` integer
  - `sshReady` boolean — true when SSH should work now. Observed: a node-side probe saw the guest sshd answer. Falls back to the running-status guess on nodes not yet reporting probes (sshState=unverified).
  - `sshState` 'ready' | 'booting' | 'unverified' | 'offline' — why sshReady is what it is. booting = the VM is running but its guest OS has not started sshd yet (GPU VMs take minutes); unverified = no probe signal for this node, sshReady is a guess; offline = the VM is not running.
  - `sshStateReason` string — human-readable explanation of sshState, safe to show to the customer
  - `sshUser` string — login user the gateway lands as inside the VM (e.g. ubuntu)
  - `startedAt` string
  - `status` string, required
  - `statusReason` string — human-readable cause for failed/stuck states
  - `templateInfo` VmTemplateInfo
    - `name` string, required
    - `osType` string, required
    - `osVersion` string
  - `terminatedAt` string — RFC3339 time the VM was terminated. Set only once status is "terminated" (a stopped/failed VM can restart, so it has none); absent while the VM is live. On a terminated VM, healthy is false and provisioningStage is absent.
  - `tier` string, required
  - `updatedAt` string, required

## Other responses

- `401` — Missing or invalid API key
- `403` — API key lacks the required scope
- `404` — Resource not found

## Changes

- **2026-08-25** `5dd7f6dfe365` — 2 info
  - added the optional property `hostDiskFreeGb` to the response with the `200` status
  - added the optional property `hostDiskTotalGb` to the response with the `200` status
- **2026-08-16** `ed76b41e8006` — 1 info
  - added the optional property `terminatedAt` to the response with the `200` status
- **2026-08-14** `3b21cbc21883` — 2 info
  - added the optional property `sshState` to the response with the `200` status
  - added the optional property `sshStateReason` to the response with the `200` status

[Change history](https://skmtc.dev/openrelay/apis/openrelay-api/changes/v1/vms/:id/detail/get.md)

---

[API](https://skmtc.dev/openrelay/apis/openrelay-api.md) · [All operations](https://skmtc.dev/openrelay/apis/openrelay-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/openrelay/openrelay-api/revisions/3dc47c9667e8/schema)
