---
title: "Train a Reflex"
method: POST
path: "/v1/fine_tuning/jobs"
tags: ["fine-tuning"]
---

# Train a Reflex

`POST /v1/fine_tuning/jobs`

Start a training job. OpenAI fine-tuning-compatible, with two differences: training data is **inline** (`training_data`, no Files API) and there are **no hyperparameters**. `model` selects the base to train from — omit it for a from-scratch cold start, or pass any custom or default reflex to warm-start from its weights. A small Reflex trains in about 30 seconds. Provide exactly one input mode — `training_data`, `generate`, or `label_data`.

## Request body

- CreateFineTuningJobRequest — Provide exactly one input: `training_data`, `generate`, or `label_data`. The training set must end up with 2+ labels and 5+ examples per label.
  - `model` string — What to train from (OpenAI-style). Omit for a from-scratch cold start, or pass a custom or default reflex to warm-start from its weights: a model you trained (its `suffix` or job id) or a built-in reflex name like `guardrail`.
  - `suffix` string — Names the served model. Becomes `fine_tuned_model` on success.
  - `labels` string[] — The classes. 2+ required for `generate` and `label_data`; inferred from `training_data` if omitted.
  - `webhook_url` string — An `https` URL that receives a signed webhook when the job reaches `succeeded`, `failed`, or `cancelled`.
  - `auto_train` boolean — Train as soon as data prep finishes. Set `false` to pause at `prepared` for review, then call `POST /v1/fine_tuning/jobs/{job_id}/train`.
  - `training_data` object[] — Labeled rows you supply (input mode 1).
    - `text` string, required — The raw text to classify.
    - `label` string, required — The class this text belongs to.
  - `generate` object — Input mode 2: synthesize training data from a description.
    - `description` string — What the classifier is for.
    - `examples_per_label` integer — Examples to synthesize per label. 5–1000.
  - `label_data` object — Input mode 3: sort your unlabeled text into your classes.
    - `texts` string[] — Unlabeled strings, up to 20,000. Minimum is your label count × 5.
    - `description` string — Context for more accurate labeling.

## Response `200`

The created job.

- FineTuningJob — An OpenAI-compatible `fine_tuning.job`, with additive Reflex fields (`labels`, `trained_examples`, `result`, `suffix`).
  - `id` string, required — Job id, prefixed `ftjob-`.
  - `object` string, required — Always `fine_tuning.job`.
  - `model` string, required — What the job trained from: the reflex you warm-started from, or the from-scratch base for a cold start.
  - `created_at` integer, required — Unix timestamp (seconds) at creation.
  - `finished_at` integer, nullable, required — Unix timestamp at a terminal state, else null.
  - `fine_tuned_model` string, nullable, required — Served model name once `succeeded` (the `suffix`, or the job id if none).
  - `status` 'queued' | 'validating_files' | 'running' | 'succeeded' | 'failed' | 'cancelled', required — `validating_files` is the data-prep phase for `generate`/`label_data` jobs.
  - `labels` string[], required — The classes this job trained on.
  - `trained_examples` integer, required — Number of training examples.
  - `hyperparameters` object, required — Fully managed.
    - `n_epochs` integer, required — Passes over the training set.
    - `batch_size` string, required — Batch size, always `auto`.
    - `learning_rate_multiplier` string, required — Learning-rate multiplier, always `auto`.
  - `result` object, nullable, required — `{accuracy, f1_score}` when `succeeded`, else null. Each value may be null.
    - `accuracy` number, nullable, required — Held-out accuracy of the trained model.
    - `f1_score` number, nullable, required — Held-out macro F1 of the trained model.
  - `error` object, nullable, required — `{code, message, param}` when `failed`, else null.
    - `code` string, nullable, required — Machine-readable failure code.
    - `message` string, nullable, required — Human-readable reason the training job failed.
    - `param` string, nullable, required — The request field that caused the failure.
  - `suffix` string, nullable, required — The suffix supplied at creation, else null.

## Other responses

- `400` — Malformed request — missing or invalid fields.
- `401` — Missing or invalid API key.
- `429` — Rate limited — retry after the interval in the Retry-After header.
- `500` — Internal error — safe to retry with backoff.

---

[API](https://skmtc.dev/morphllm/apis/morph-api.md) · [All operations](https://skmtc.dev/morphllm/apis/morph-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/morphllm/morph-api/revisions/b9a74274b2ab/schema)
