> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omnia-voice.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Creating a job

> Upload a training file and start a fine-tuning job.

Fine-tuning jobs are created against the API at
`https://gateway.omnia-voice.com/v1` with your workspace API key. Launching a job
is an **admin-gated** action.

## 1. Upload a training file

Fine-tuning takes a training file (JSONL). Upload it with
`POST /v1/fine_tuning/files`:

<CodeGroup>
  ```bash cURL theme={null}
  curl https://gateway.omnia-voice.com/v1/fine_tuning/files \
    -H "Authorization: Bearer $OMNIA_API_KEY" \
    -F "file=@training.jsonl"
  ```

  ```python Python theme={null}
  import requests

  BASE = "https://gateway.omnia-voice.com/v1"
  headers = {"Authorization": f"Bearer {OMNIA_API_KEY}"}

  with open("training.jsonl", "rb") as f:
      file = requests.post(
          f"{BASE}/fine_tuning/files",
          headers=headers,
          files={"file": f},
      ).json()
  ```
</CodeGroup>

The response includes the file's id, which you reference as `trainingFileId`. You
can also prepare data as a managed dataset; see
[Datasets & formats](/fine-tuning/datasets).

## 2. Create the job

Create a job with `POST /v1/fine_tuning/jobs`. Only `baseModel` is required; you
supply training data as a `trainingFileId` (or inline `training`).

<CodeGroup>
  ```bash cURL theme={null}
  curl https://gateway.omnia-voice.com/v1/fine_tuning/jobs \
    -H "Authorization: Bearer $OMNIA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "baseModel": "meta-llama/Llama-3.1-8B-Instruct",
      "name": "support-tone-v1",
      "suffix": "support-v1",
      "trainingFileId": "<file-id>",
      "validationFileId": "<validation-file-id>",
      "method": "supervised",
      "seed": 42,
      "hyperparameters": {
        "n_epochs": 3,
        "learning_rate": 0.0001,
        "batch_size": 8,
        "lora": true,
        "lora_r": 16,
        "lora_alpha": 32
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  BASE = "https://gateway.omnia-voice.com/v1"
  headers = {
      "Authorization": f"Bearer {OMNIA_API_KEY}",
      "Content-Type": "application/json",
  }

  job = requests.post(
      f"{BASE}/fine_tuning/jobs",
      headers=headers,
      json={
          "baseModel": "meta-llama/Llama-3.1-8B-Instruct",
          "name": "support-tone-v1",
          "suffix": "support-v1",
          "trainingFileId": "<file-id>",
          "validationFileId": "<validation-file-id>",
          "method": "supervised",
          "seed": 42,
          "hyperparameters": {
              "n_epochs": 3,
              "learning_rate": 0.0001,
              "batch_size": 8,
              "lora": True,
              "lora_r": 16,
              "lora_alpha": 32,
          },
      },
  ).json()
  ```
</CodeGroup>

A successful create returns the new job's id:

```json theme={null}
{ "id": "<job-id>" }
```

Poll the job with `GET /v1/fine_tuning/jobs/{id}` to follow its `status`
(`queued` → `running` → `succeeded`/`failed`/`cancelled`), events, and, once
finished, its `trained_tokens` and the resulting model.

### Fields

| Field                      | Required | Description                                   |
| -------------------------- | -------- | --------------------------------------------- |
| `baseModel`                | Yes      | The base model to fine-tune (a catalog id).   |
| `training`                 | No       | Inline training data.                         |
| `validation`               | No       | Inline validation data.                       |
| `trainingFileId`           | No       | Id of an uploaded training file.              |
| `validationFileId`         | No       | Id of a held-out file for validation metrics. |
| `name`                     | No       | Human-readable name for the job.              |
| `suffix`                   | No       | Label appended to the resulting model name.   |
| `seed`                     | No       | For reproducibility.                          |
| `method`                   | No       | `supervised` (LoRA or full) or `spec-draft`.  |
| `hyperparameters`          | No       | Supervised training settings (see below).     |
| `specDraftHyperparameters` | No       | Settings for the `spec-draft` method.         |
| `integrations`             | No       | External integrations for the job.            |

### Supervised hyperparameters

All supervised hyperparameters are optional with sensible defaults; you only set
what you want to override.

<AccordionGroup>
  <Accordion title="Training schedule" icon="clock">
    | Field           | Description                                          |
    | --------------- | ---------------------------------------------------- |
    | `n_epochs`      | Number of passes over the training data.             |
    | `learning_rate` | Optimizer learning rate.                             |
    | `batch_size`    | Examples per training step.                          |
    | `warmup_ratio`  | Fraction of steps used to warm up the learning rate. |
    | `weight_decay`  | L2 regularization strength.                          |
    | `max_grad_norm` | Gradient-clipping threshold.                         |
  </Accordion>

  <Accordion title="Sequence handling" icon="ruler">
    | Field            | Description                                     |
    | ---------------- | ----------------------------------------------- |
    | `context_length` | Maximum sequence length for training.           |
    | `packing`        | Pack multiple short examples into one sequence. |
  </Accordion>

  <Accordion title="LoRA" icon="layer-group">
    | Field          | Description                                                     |
    | -------------- | --------------------------------------------------------------- |
    | `lora`         | `true` for LoRA adapter training, `false` for full fine-tuning. |
    | `lora_r`       | LoRA rank.                                                      |
    | `lora_alpha`   | LoRA alpha (scaling).                                           |
    | `lora_dropout` | LoRA dropout.                                                   |
  </Accordion>
</AccordionGroup>

## 3. Track the job

List jobs with `GET /v1/fine_tuning/jobs`, and poll a single job with
`GET /v1/fine_tuning/jobs/{id}` to watch its status and events:

<CodeGroup>
  ```bash cURL theme={null}
  curl https://gateway.omnia-voice.com/v1/fine_tuning/jobs/{id} \
    -H "Authorization: Bearer $OMNIA_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  BASE = "https://gateway.omnia-voice.com/v1"
  headers = {"Authorization": f"Bearer {OMNIA_API_KEY}"}

  job = requests.get(f"{BASE}/fine_tuning/jobs/{id}", headers=headers).json()
  ```
</CodeGroup>

Status progresses through `queued → running → succeeded` (or `failed` /
`cancelled`). **Events and checkpoints** are available while the job runs. Cancel
or delete a job with `DELETE /v1/fine_tuning/jobs/{id}`.

<Note>
  Billing happens **once, on completion**, from the trained-token count. Because
  `trained_tokens` isn't known until the run finishes, the create-time gate uses an
  **estimated-token budget**: a workspace can't launch training it can't pay for. A
  job that fails or is cancelled is not billed.
</Note>

## Next

<Card title="Deploy the model" icon="server" href="/fine-tuning/deploy-model">
  Once the job succeeds, deploy it to a dedicated endpoint.
</Card>
