---
title: "Publish a signed kernel manifest + PTX text"
method: POST
path: "/kernels"
tags: ["kernels"]
---

# Publish a signed kernel manifest + PTX text

`POST /kernels`

FEATURE-GATED: this route is only mounted when the gateway is
built with `--features kernel-registry-api`; the default build
does not register it (request 404s at the router). When the
feature is on but `TENSOR_WASM_API_KERNEL_HMAC_KEY` is unset the
handler returns `503 kernel_registry_not_configured`.

Publishes a signed `KernelManifest` plus its PTX source. The
registry re-verifies that `BLAKE3(ptx_text)` matches
`manifest.digest` and that the manifest's HMAC-SHA256 signature
verifies under the server's configured key before persisting.

Authorization is stricter than the other routes: in addition to
`bearer_auth` + `tenant_scope`, the caller's bearer token must
appear in the `TENSOR_WASM_API_KERNEL_PUBLISH_TOKENS` allowlist
(the **kernel-publish** scope). Dev mode (empty
`TENSOR_WASM_API_TOKENS`) rejects every publish with
`403 kernel_publish_disabled_in_dev_mode`. See
crates/tensor-wasm-api/src/kernels.rs.

## Headers

- `X-TensorWasm-Tenant` integer

## Request body

- PublishKernelRequest — Body of `POST /kernels`. Mirrors the `tensor_wasm_api::kernels::PublishKernelRequest` Rust struct.
  - `manifest` KernelManifest, required — Signed kernel manifest. Mirrors the `tensor_wasm_jit::registry::KernelManifest` Rust struct (`#[non_exhaustive]`, so additional fields may appear in future revisions). `digest` and `signature` are fixed 32-byte arrays serialized by serde as JSON arrays of 32 integers (0-255); the HMAC `signature` tag is public by design (it authenticates authorship, the signing key is the secret).
    - `name` string, required — Stable kernel name (e.g. `matmul.f32`).
    - `version` string, required — SemVer-style version (e.g. `1.0.0`).
    - `sm_version` integer, required — CUDA compute capability the PTX targets (e.g. 80 for sm_80).
    - `digest` integer[], required — BLAKE3 hash of the PTX text (32 bytes).
    - `signature` integer[], required — HMAC-SHA256 tag over the canonical signed bytes (32 bytes).
    - `published_unix_ms` integer, required — Wall-clock publish timestamp (Unix millis).
    - `publisher` string, required — Publisher identifier (typically a tenant id or signing-key id).
  - `ptx_text` string, required — PTX source. The server computes BLAKE3 over the UTF-8 bytes and requires a match with `manifest.digest` before the HMAC signature check.

## Response `201`

Kernel published; canonical name/version echoed back.

- PublishKernelResponse — Body of a successful `201 Created` from `POST /kernels`. Echoes the canonical key so the client can confirm what was stored.
  - `name` string, required
  - `version` string, required

## Other responses

- `400` — `digest_mismatch` (BLAKE3 of `ptx_text` did not match `manifest.digest`) or `invalid_request` (other registry rejection). Carries the native `{error:{kind,message}}` envelope.
- `401` — Missing or unrecognised bearer token
- `403` — `kernel_publish_disabled_in_dev_mode` (gateway in dev mode), `kernel_publish_scope_required` (token not in `TENSOR_WASM_API_KERNEL_PUBLISH_TOKENS`), `bad_signature` (HMAC verification failed), or `publisher_not_allowed` (manifest publisher not in the registry allowlist).
- `409` — `already_registered` — a manifest with the same `name@version` is already present.
- `413` — Request body exceeded the 64 MiB cap enforced by axum's `DefaultBodyLimit::max`. Often rendered as a bare 413 with no body when the limit is hit during streaming.
- `429` — Per-token QPS + burst exceeded. The `Retry-After` header carries the wait in integer seconds (RFC 9110 §10.2.3).
- `500` — Underlying wasmtime or host failure
- `503` — Kernel registry routes are mounted but the backing registry is not configured: `TENSOR_WASM_API_KERNEL_HMAC_KEY` is unset, so the handler returns `503 kernel_registry_not_configured`. (The publish path can also surface `kernel_registry_storage_error` here on a backend I/O failure.)

---

[API](https://skmtc.dev/craton-co/apis/tensorwasm-http-api.md) · [All operations](https://skmtc.dev/craton-co/apis/tensorwasm-http-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/craton-co/tensorwasm-http-api/revisions/d363e13d8640/schema)
