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

# Submit Host Profile

`POST /servers/tdx/host_profiles`

## Request

- Base URL: `https://api.chutes.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.chutes.ai/servers/tdx/host_profiles`
- Auth: API key in header `Authorization`

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

One of four distinct operations: this REGISTERS, POST /servers/tdx/host_profiles/status
RESOLVES a class (is it known, and for which images), POST /servers/tdx/preflight CHECKS whether
one specific image can boot, and GET /servers/tdx/host_profiles LISTS the generated set. A miner
reaches this only when the status lookup reports the class is not on file. 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: One host class, as chutes-cvm's ``HostProfile.to_api_profile()`` submits it. A direct translation of the client's own model: the RTMR0 determinants and nothing else. Stored == hashed == required, one set. An unhashed field stored beside a hashed one would re-split the class at the byte level -- two hosts that measure identically would differ in the stored row, and first-write-wins would silently drop one of them. That is why host RAM, BDFs, DMI strings and the lspci tree are absent rather than merely excluded. Every block forbids extras, so a client that adds a key 422s until the API models it: add the field here, deploy, then roll out the client.
  - `gpus` HostProfileGpuDevice[], required
    - `vendor` string, required
    - `device_id` string, required
    - `pci_class` string, required
    - `numa_node` integer, required
    - `bars` HostProfilePciBar[], required
      - `index` integer, required
      - `size_mb` integer, required
      - `kind` string, required
  - `nvswitches` HostProfileNvswitchDevice[]
    - `vendor` string, required
    - `device_id` string, required
    - `pci_class` string, required
    - `numa_node` integer, required
    - `bars` HostProfilePciBar[], required
      - `index` integer, required
      - `size_mb` integer, required
      - `kind` string, required
  - `ib_devices` HostProfileIbDevice[]
    - `vendor` string, required
    - `device_id` string, required
    - `pci_class` string, required
    - `numa_node` integer, required
    - `bars` HostProfilePciBar[], required
      - `index` integer, required
      - `size_mb` integer, required
      - `kind` string, required
    - `is_bridge_pf` boolean
    - `is_vf` boolean
  - `cpu` HostProfileCpu, required: The host CPU facts that reach RTMR0: the guest -smp and the SMBIOS Type-4 identity. Mirrors chutes-cvm's `HostCpu` field for field. `processor_id` is nullable -- CPUID leaf-1 is unreadable on some hosts -- but the key is required, and generation refuses a null rather than measuring its own host's CPU.
    - `count` integer, required
    - `sockets` integer, required
    - `vendor` string, required
    - `processor_id` string, nullable, required
  - `memory` HostProfileMemory, required: Guest RAM, as the client resolved it. Not host RAM: the sizing rules are per-GPU-profile and live in chutes-cvm, so the client sends the answer. Storing the host total instead would split hosts that measure identically -- 2007 and 2011 GB are one H200 class.
    - `guest_gb` integer, required
  - `numa` HostProfileNuma, required: Host NUMA node count: it picks the guest's memory-map and PXB-PCIe grouping.
    - `node_count` integer, required
  - `qemu` HostProfileQemu, required: The QEMU that builds the guest ACPI measured into RTMR0.
    - `qemu_version` string, required

## Response `200`

Successful Response

- string

## Other responses

- `422`: Validation Error

## Changes

- **2026-10-16** `23e8895b217d`: 5 breaking, 2 info
  - the response's body type changed from `object` to `string` for status `200`
  - removed the required property `detail` from the response with the `200` status
  - removed the required property `fingerprint` from the response with the `200` status
  - removed the required property `status` from the response with the `200` status
  - …3 more
- **2026-09-20** `6543e32b21d3`: 7 breaking, 18 warning, 2 info
  - added the new required request property `cpu/count`
  - added the new required request property `cpu/processor_id`
  - added the new required request property `cpu/vendor`
  - added the new required request property `gpus`
  - …23 more
- **2026-09-15** `fe1de11b2a0e`: 2 info
  - added the new optional request property `gpu/pci_bars`
  - added the new optional request property `gpu/pci_class`
- **2026-08-27** `7be1aa2fe1a0`: 1 warning
  - deleted the `query` request parameter `dry_run`
- **2026-08-26** `8d909638091e`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/chutes/apis/chutes-api/changes/servers/tdx/host_profiles/post.md)

---

[API](https://skmtc.dev/chutes/apis/chutes-api.md) - [All operations](https://skmtc.dev/chutes/apis/chutes-api/llms.txt) - [OpenAPI document](https://skmtc.dev/chutes/apis/chutes-api/revisions/8add5b0e22da?raw)
