Fine-tuning jobs
Submit managed fine-tuning jobs and follow them from queue to trained model.
A fine-tuning job takes an uploaded dataset and a base model and produces a trained model, with the training loop, scheduling and checkpointing managed for you. Upload your data as a file, submit a job, poll until it finishes, then serve the result. Teams that need step-level control over the loop, for custom losses or reinforcement learning, use training runs instead.
A job moves through queued and running to succeeded, failed or cancelled. While it
runs, Stream job events carries the loss curve and any warnings. Once
it succeeds, Retrieve a fine-tuning job returns the
result_model path you hand to
Create a sampler to start serving.
Create a fine-tuning job
/v1/fine-tuning/jobsscope: trainSubmits a fine-tuning job. The training file must have finished validating and reached
ready before you submit; see Retrieve a dataset.
Body parameters
base_modelstringrequiredThe base model to fine-tune, for example Qwen/Qwen3-8B.
training_filestringrequiredID of an uploaded fine-tune file to train on.
validation_filestringID of a held-out file used to compute validation loss during training.
methodstringdefault: sftTraining method: sft (supervised fine-tuning) or dpo (direct preference optimisation).
hyperparametersobjectAn object of epochs, learning_rate, batch_size and lora_rank, all optional. Anything you
omit is chosen automatically; the job response shows the resolved values.
suffixstringNames the output model, so you can tell your fine-tunes apart later.
Submitting is not idempotent: retrying a timed-out request can start a duplicate job. Send an
Idempotency-Key header if your client retries automatically. See
Errors and retries.
curl https://api.nucleus-ai.io/v1/fine-tuning/jobs \
-H "Authorization: Bearer $NUCLEUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"base_model": "Qwen/Qwen3-8B",
"training_file": "file_9fQ2x",
"hyperparameters": { "epochs": 3, "lora_rank": 32 },
"suffix": "support-assistant"
}'{
"id": "ftjob_7Kd1p",
"status": "queued",
"base_model": "Qwen/Qwen3-8B",
"training_file": "file_9fQ2x",
"hyperparameters": {
"epochs": 3,
"lora_rank": 32,
"learning_rate": "auto"
},
"result_model": null
}List fine-tuning jobs
/v1/fine-tuning/jobsscope: readReturns your fine-tuning jobs, so you can see what is queued, running and finished across
the account. See Pagination for how limit, offset and the cursor object
behave across list endpoints.
Query parameters
statusstringFilter to one status: queued, running, succeeded, failed or cancelled.
project_idstringOnly jobs in this project.
limitintegerMaximum number of jobs to return.
offsetintegerNumber of jobs to skip from the start of the list.
curl "https://api.nucleus-ai.io/v1/fine-tuning/jobs?status=running" \
-H "Authorization: Bearer $NUCLEUS_API_KEY"{
"data": [
{
"id": "ftjob_7Kd1p",
"status": "running",
"progress": 0.42
}
],
"cursor": { "offset": 0, "total_count": 3 }
}Retrieve a fine-tuning job
/v1/fine-tuning/jobs/{job_id}scope: readReturns one job, including progress, trained_tokens and, on success, the trained model.
This is the endpoint to poll after submitting.
result_model is a nucleus:// path: pass it straight to
Create a sampler to serve the model. It is the
handoff point from training to serving. training_run_id identifies the underlying
training run, and metrics reports the final training and
validation loss.
Path parameters
job_idstringrequiredID of the job, from the create response.
curl https://api.nucleus-ai.io/v1/fine-tuning/jobs/ftjob_7Kd1p \
-H "Authorization: Bearer $NUCLEUS_API_KEY"{
"id": "ftjob_7Kd1p",
"status": "succeeded",
"progress": 1.0,
"trained_tokens": 8420117,
"training_run_id": "run_3Bz",
"result_model": "nucleus://run_3Bz:train:0/sampler_weights/000240",
"metrics": {
"final_loss": 0.72,
"val_loss": 0.81
}
}Cancel a fine-tuning job
/v1/fine-tuning/jobs/{job_id}/cancelscope: trainCancels a queued or running job. Cancelling stops the run and stops the meter:
billed_tokens_so_far is the total you are charged for. The job reports cancelling while
it shuts down, then settles at cancelled.
Path parameters
job_idstringrequiredID of the job to cancel.
curl -X POST https://api.nucleus-ai.io/v1/fine-tuning/jobs/ftjob_7Kd1p/cancel \
-H "Authorization: Bearer $NUCLEUS_API_KEY"{
"id": "ftjob_7Kd1p",
"status": "cancelling",
"billed_tokens_so_far": 3910442
}Stream job events
/v1/fine-tuning/jobs/{job_id}/eventsscope: readReturns the job's event log: step-by-step loss values, epoch boundaries and warnings such as validation loss rising. This is how you watch the loss curve and judge whether a run is going well while it is still spending tokens.
With stream=true the response is Server-Sent Events (text/event-stream) and events
arrive as the trainer emits them; use curl -N to disable buffering. Without it you get the
events accumulated so far in one response. Each event carries an id; if a stream
disconnects, pass the last ID you saw as after to resume without replaying old events.
Query parameters
afterstringEvent ID to resume from. Only events after this ID are returned.
streambooleanWhen true, stream events over SSE as they happen.
curl -N "https://api.nucleus-ai.io/v1/fine-tuning/jobs/ftjob_7Kd1p/events?stream=true" \
-H "Authorization: Bearer $NUCLEUS_API_KEY"{ "id": "evt_04", "level": "info",
"step": 120, "loss": 0.94,
"message": "epoch 2/3" }
{ "id": "evt_05", "level": "warn",
"message": "val loss rising, possible overfit" }