# Publish jobs

URL: https://docs.hanzo.ai/docs/openapi/train/post-train-jobs-by-id-publish

> Publishes a job's output under a name.

`POST /v1/train/jobs/{id}/publish`

> [Train →](https://docs.hanzo.ai/docs/openapi/train) · [All API references →](https://docs.hanzo.ai/docs/openapi) · [Get started →](https://docs.hanzo.ai/docs/guides)

|               |                                                   |
| ------------- | ------------------------------------------------- |
| **Address**   | `https://api.hanzo.ai/v1/train/jobs/{id}/publish` |
| **Method**    | `POST`                                            |
| **Operation** | `post_train_jobs_by_id_publish`                   |
| **Auth**      | `Authorization: Bearer $HANZO_API_KEY`            |

Publishes a job's output under a name. Only a succeeded job's
output is publishable; a rejected one broke its regression budget and needs
force, which the record keeps. The output must be stored. A capability is
published with its route — the question keys it answers and, per key, the
exact question (`{"type": "choice"|"score"|"noul", "labels": [...]}`) — the
base SHA-256 its result names, and its form: head for a readout, full for
every other adaptation. A route that claims a question another of the org's
published capabilities claims is 409 route\_conflict. A name the org already
published moves to this job. Every org's published capabilities are what the
decision service installs.

## Request

10 fields, body `application/json` (required).

| Field                    | In   | Type          | Required | Description                                                                                                                          |
| ------------------------ | ---- | ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `id`                     | path | string        | yes      | ID names the job.                                                                                                                    |
| `force`                  | body | boolean       | —        | Force publishes a rejected job's output, and is recorded.                                                                            |
| `id`                     | body | string        | —        | ID names the job.                                                                                                                    |
| `name`                   | body | string        | —        | Name is the published name; the output's name when absent.                                                                           |
| `route`                  | body | train.Route   | —        |                                                                                                                                      |
| `route.keys`             | body | string\[]     | —        | Keys are the question keys it answers.                                                                                               |
| `route.options`          | body | object        | —        | Options narrows a key to one question: a question under that key routes here only when its type and option labels are exactly these. |
| `route.options.*`        | body | train.Options | —        |                                                                                                                                      |
| `route.options.*.labels` | body | string\[]     | —        | Labels are its option labels, in order: a choice's criteria, a score's levels as text, a noul's two sides.                           |
| `route.options.*.type`   | body | string        | —        | Type is choice, score or noul.                                                                                                       |

## Response

| Status    | Body            | Meaning |
| --------- | --------------- | ------- |
| `200`     | train.Job       | ok      |
| `default` | problem-details | refused |

`200` body — 78 fields.

| Field                         | In   | Type              | Always | Description                                                                                                                            |
| ----------------------------- | ---- | ----------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `adaptation`                  | body | train.Adaptation  | —      |                                                                                                                                        |
| `adaptation.alpha`            | body | number (double)   | —      | Alpha is an adapter's scale.                                                                                                           |
| `adaptation.basis`            | body | string            | —      | Basis is a basis artifact, by sha256 or `basis://&lt;base&gt;/&lt;name&gt;`.                                                           |
| `adaptation.chose`            | body | train.Chose       | —      |                                                                                                                                        |
| `adaptation.chose.mode`       | body | string            | —      | Mode is the mode the job runs.                                                                                                         |
| `adaptation.chose.why`        | body | string            | —      | Why says what decided it.                                                                                                              |
| `adaptation.mode`             | body | string            | —      | Mode is full, readout (the head alone, over the frozen base), lora, qlora, basis or auto.                                              |
| `adaptation.rank`             | body | integer (int64)   | —      | Rank is an adapter's rank, or how many of a basis's directions are used.                                                               |
| `adaptation.residual_rank`    | body | integer (int64)   | —      | ResidualRank is the rank of an orthonormal residual learned beside a basis's coefficients; 0 trains the coefficients alone.            |
| `adaptation.sources`          | body | string\[]         | —      | Sources are lora artifacts (sha256) a basis is built from, in place of Basis.                                                          |
| `adaptation.targets`          | body | string\[]         | —      | Targets are the modules an adapter or a basis attaches to.                                                                             |
| `artifacts`                   | body | train.artifact\[] | —      | Artifacts are its outputs.                                                                                                             |
| `artifacts[].created`         | body | integer (int64)   | —      | Created is when it was registered, unix seconds.                                                                                       |
| `artifacts[].job`             | body | string            | —      | Job is the job that produced it; empty for an upload.                                                                                  |
| `artifacts[].kind`            | body | string            | —      | Kind is checkpoint, lora, capability, basis or merged, or dataset for an upload.                                                       |
| `artifacts[].meta`            | body | any               | —      | Meta describes it: its base and revision, its modules, a basis's address.                                                              |
| `artifacts[].name`            | body | string            | —      | Name labels it.                                                                                                                        |
| `artifacts[].sha256`          | body | string            | —      | SHA256 is the hex digest of its bytes, and its name in the object store.                                                               |
| `artifacts[].size`            | body | integer (int64)   | —      | Size is its byte count.                                                                                                                |
| `artifacts[].state`           | body | string            | —      | State is pending until its bytes are read back, then stored; deleted once the org deleted it or it outlived its retention unpublished. |
| `base_model`                  | body | string            | —      |                                                                                                                                        |
| `created`                     | body | integer (int64)   | —      | Created, Started and Ended are unix seconds; 0 is not yet.                                                                             |
| `created_by`                  | body | string            | —      | CreatedBy is the principal that created it.                                                                                            |
| `dataset`                     | body | train.Dataset     | —      |                                                                                                                                        |
| `dataset.splits`              | body | object            | —      | Splits maps a role (train, validation) to the dataset's own split name.                                                                |
| `dataset.splits.*`            | body | string            | —      |                                                                                                                                        |
| `dataset.uri`                 | body | string            | —      | URI names the data.                                                                                                                    |
| `ended`                       | body | integer (int64)   | —      |                                                                                                                                        |
| `error`                       | body | string            | —      | Error says why a job failed or stopped.                                                                                                |
| `evaluation`                  | body | train.Evaluation  | —      |                                                                                                                                        |
| `evaluation.suites`           | body | string\[]         | —      | Suites are the suites the job is meant to improve.                                                                                     |
| `from`                        | body | string            | —      |                                                                                                                                        |
| `id`                          | body | string            | —      | ID names the job.                                                                                                                      |
| `objective`                   | body | train.Objective   | —      |                                                                                                                                        |
| `objective.loss`              | body | string            | —      | Loss is `cross_entropy`.                                                                                                               |
| `objective.terms`             | body | train.Term\[]     | —      | Terms are added to each row's loss.                                                                                                    |
| `objective.terms[].kind`      | body | string            | —      | Kind names the term.                                                                                                                   |
| `objective.terms[].margin`    | body | number (double)   | —      | Margin is a hinge's margin, in logits.                                                                                                 |
| `objective.terms[].weight`    | body | number (double)   | —      | Weight scales it; 0 is off.                                                                                                            |
| `output`                      | body | train.Output      | —      |                                                                                                                                        |
| `output.kind`                 | body | string            | —      | Kind is checkpoint, lora, capability, basis or merged.                                                                                 |
| `output.name`                 | body | string            | —      | Name labels it.                                                                                                                        |
| `project`                     | body | string            | —      | Project is the creator's project scope.                                                                                                |
| `protect`                     | body | train.Protect     | —      |                                                                                                                                        |
| `protect.budget`              | body | train.Budget      | —      |                                                                                                                                        |
| `protect.budget.accuracy`     | body | number (double)   | —      | Accuracy is the largest accuracy drop allowed.                                                                                         |
| `protect.budget.ece`          | body | number (double)   | —      | ECE is the largest calibration-error rise allowed.                                                                                     |
| `protect.capabilities`        | body | string\[]         | —      | Capabilities are capability artifacts, by sha256.                                                                                      |
| `protect.distillation`        | body | boolean           | —      | Distillation adds KL to the base's answers on a preservation set drawn from the suites.                                                |
| `protect.projection`          | body | train.Projection  | —      |                                                                                                                                        |
| `protect.projection.strength` | body | number (double)   | —      | Strength is λ in \[0, 1]; absent is 1, the whole of P g removed.                                                                       |
| `protect.suites`              | body | string\[]         | —      | Suites are capabilities the base already has, by suite.                                                                                |
| `published`                   | body | any               | —      | Published is the publish record, once published.                                                                                       |
| `resources`                   | body | train.Resources   | —      |                                                                                                                                        |
| `resources.budget`            | body | integer (int64)   | —      | Budget bounds what the job's compute costs, in US cents; 0 is none beyond the payer's balance.                                         |
| `resources.devices`           | body | string\[]         | —      | Devices are the accelerator kinds the job may run on — cuda, rocm, metal, vulkan, cpu; none named is any its base runs.                |
| `resources.machines`          | body | string\[]         | —      | Machines are the org's linked machines by name; the first leads.                                                                       |
| `resources.max_seconds`       | body | integer (int64)   | —      | MaxSeconds bounds the device-seconds the job's tasks use together; 0 is none.                                                          |
| `resources.steps`             | body | integer (int64)   | —      | Steps bounds optimizer steps; 0 runs the plan.                                                                                         |
| `result`                      | body | any               | —      | Result is the lead's evaluation and verdict, once reported.                                                                            |
| `revision`                    | body | string            | —      |                                                                                                                                        |
| `started`                     | body | integer (int64)   | —      |                                                                                                                                        |
| `status`                      | body | string            | —      | Status is queued, running, evaluating, succeeded, rejected, failed, cancelled or stopped.                                              |
| `tasks`                       | body | train.TaskView\[] | —      | Tasks are its units of execution.                                                                                                      |
| `tasks[].device`              | body | string            | —      | Device is the accelerator class it runs on — gpu or cpu — and Devices how many.                                                        |
| `tasks[].devices`             | body | integer (int64)   | —      |                                                                                                                                        |
| `tasks[].held`                | body | integer (int64)   | —      |                                                                                                                                        |
| `tasks[].host`                | body | string            | —      | Host is the machine that claimed it.                                                                                                   |
| `tasks[].id`                  | body | string            | —      | ID names the task.                                                                                                                     |
| `tasks[].machine`             | body | string            | —      | Machine is the machine it was placed on, or empty for any.                                                                             |
| `tasks[].role`                | body | string            | —      | Role is lead or join.                                                                                                                  |
| `tasks[].seconds`             | body | integer (int64)   | —      | Seconds are the device-seconds its reports metered, and Held those held for it.                                                        |
| `tasks[].seen`                | body | integer (int64)   | —      | Seen is its last report, unix seconds.                                                                                                 |
| `tasks[].status`              | body | string            | —      | Status is open, claimed, done or lost.                                                                                                 |
| `usage`                       | body | train.Usage       | —      |                                                                                                                                        |
| `usage.cost_micro_usd`        | body | integer (int64)   | —      | CostMicroUSD is what Seconds were charged, in micro-USD: 0 on the org's own machines.                                                  |
| `usage.held`                  | body | integer (int64)   | —      | Held are the device-seconds held beyond Seconds; 0 once it ended.                                                                      |
| `usage.seconds`               | body | integer (int64)   | —      | Seconds are the device-seconds used.                                                                                                   |

Failure carries the platform error shape — see [Errors](https://docs.hanzo.ai/docs/errors).

## Examples

**CLI**

`hanzo` has no subcommand for this operation — the CLI serves only what cloud's live route table confirms. Use HTTP or an SDK.

**SDK**

**.ts**

```ts
import { Configuration, TrainApi } from 'hanzoai';

const api = new TrainApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postTrainJobsByIdPublish({ id: 'id', force: false, id: "<id>" });
```

**.py**

```python
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import TrainApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = TrainApi(client).post_train_jobs_by_id_publish(id='id', force=False, id="<id>")
```

**.go**

```go
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.TrainAPI.PostTrainJobsByIdPublish(context.Background()).Execute()
if err != nil {
	return err
}
```

**.rs**

```rust
use hanzo_client::apis::{configuration::Configuration, train_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = train_api::post_train_jobs_by_id_publish(&cfg, Default::default()).await?;
```

**.java**

```java
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.TrainApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new TrainApi(client).postTrainJobsByIdPublish();
```

**HTTP**

```bash
curl -X POST https://api.hanzo.ai/v1/train/jobs/<id>/publish \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "force": false,
       "id": "<id>"
     }'
```

**MCP**

MCP declares no tool for **train** — `tools/list` on `https://api.hanzo.ai/v1/mcp` names the products it does reach. Use HTTP or an SDK.

---

[Train API](https://docs.hanzo.ai/docs/openapi/train) · [All Hanzo APIs](https://docs.hanzo.ai/docs/openapi) · [Interactive reference](https://docs.hanzo.ai/docs/openapi/reference)
