---
title: "Submit Host Profile"
method: POST
path: "/servers/tdx/host_profiles"
tags: ["Servers"]
---

# Submit Host Profile

`POST /servers/tdx/host_profiles`

Register a host class (sek8s `discover-profile.sh` output) so Chutes can measure it.

One of three distinct operations: this REGISTERS, POST /servers/tdx/preflight CHECKS
launchability, and GET /servers/tdx/host_profiles LISTS the generated set. A miner reaches this
only when preflight says the class is not yet launchable. The API owns the fingerprint -- the
miner sends raw platform metadata and gets back the class's retention lifecycle, which only ever
advances:

  * `accepted` -- a measurement has already been generated for this class; retained from here on
  * `pending`  -- parked in object storage, awaiting its first measurement generation

A real submission is always stored, so this never returns `unknown`. It answers only whether the
class has been measured at all; whether the caller's specific image can boot is preflight's job.
Signed by the miner hotkey, so the signature covers the request body.

## Headers

- `X-Chutes-Hotkey` string, nullable
- `X-Chutes-Signature` string, nullable
- `X-Chutes-Nonce` string, nullable
- `Authorization` string, nullable

## Request body

- HostProfile — The document sek8s ``discover-profile.sh`` emits for one machine -- the whole submitted body, and what gets stored. Every key the script emits is modeled and every block forbids extras, so compatibility is one-way: an older script still validates (defaults fill in), but a script that adds a key 422s until the API models it. Add the field here, deploy, then roll out the script.
  - `hostname` string, nullable
  - `timestamp` string, nullable
  - `host` HostProfilePlatform — DMI/SMBIOS identity (board, BIOS, chassis) plus OS release. Recorded, not fingerprinted -- BIOS revisions move independently of the host class.
    - `product_name` string
    - `board_vendor` string
    - `board_name` string
    - `bios_vendor` string
    - `bios_version` string
    - `bios_date` string
    - `os_version_id` string
  - `launch_determinism` HostProfileQemu, required — QEMU build and the ``-cpu`` string it launches with -- both RTMR0 determinants. Wire key is ``launch_determinism``. Its last three members restate ``numa`` and ``cpu``; they are declared so real submissions validate, but nothing reads them (``fingerprint`` takes those values from their canonical block, so a disagreeing copy cannot shift it).
    - `qemu_version` string, required
    - `qemu_version_full` string
    - `cpu_args` string
    - `numa_node_count` integer
    - `numa_topology_eligible` boolean
    - `host_cpu_topology` string
  - `gpu` HostProfileGpu, required — Passthrough GPU inventory: PCI ids and addresses, count, BAR/VRAM sizing, VBIOS.
    - `pci_device_ids` string[]
    - `bdfs` string[]
    - `count` integer, required
    - `vram_gb` number, nullable
    - `bar_size_mb` integer
    - `numa_nodes` integer[]
    - `vbios` string[]
  - `pci_topology` string, nullable
  - `cpu` HostProfileCpu, required — Host CPU topology and the identity fields RTMR0 depends on.
    - `total` integer, required
    - `sockets` integer, required
    - `cores_per_socket` integer, required
    - `threads_per_core` integer, required
    - `cpu_vendor` string
    - `cpu_processor_id` string, nullable
  - `memory` HostProfileMemory, required — Host RAM, which some profiles (e.g. B200) derive guest RAM from. The ``suggested_*`` fields are the script's own sizing advice, recorded but unused.
    - `total_gb` number, required
    - `suggested_ram_per_gpu_gb` integer
    - `suggested_total_vm_ram_gb` integer
  - `numa` HostProfileNuma, required — NUMA layout: node count, node indices, per-node cpulists.
    - `node_count` integer, required
    - `nodes` integer[]
    - `cpus_per_node` object
  - `nic` HostProfileNic — InfiniBand / Ethernet inventory, including passthrough-eligible NICs.
    - `ib_class_count` integer
    - `eth_class_count` integer
    - `ib_devices` string[]
    - `bridge_pfs` string[]
    - `passthrough_candidates` string[]
    - `passthrough_numa_nodes` integer[]
  - `nvswitch` HostProfileNvswitch — NVSwitch inventory (passthrough stubs are reproduced offline per switch).
    - `present` boolean
    - `count` integer
    - `devices` string[]
    - `numa_nodes` integer[]

## Response `200`

Successful Response

- HostProfileSubmissionResponse — Response for POST /servers/tdx/host_profiles.
  - `fingerprint` string, required
  - `status` 'accepted' | 'pending' | 'unknown', required — Retention lifecycle of a submitted host class -- monotonic, only ever advances (unknown -> pending -> accepted) and never regresses. ``accepted`` is class-level and version-agnostic: a measurement was generated for this fingerprint at some point, so the class is on the attestable set and retained (its profile is kept for RTMR0 regeneration). It is NOT the answer to "can version X launch here" -- that is POST /servers/tdx/preflight, which joins the caller's (version, rc) to the class's measurements. Submission only reports which of the three the class is in.
  - `stored` boolean, required
  - `detail` string, required

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/chutes/apis/fastapi.md) · [All operations](https://skmtc.dev/chutes/apis/fastapi/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/chutes/fastapi/revisions/7be1aa2fe1a0/schema)
