curl --request POST \
--url https://api.kiteml.com/v1/training_runs/{run_id}/cancel \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.kiteml.com/v1/training_runs/{run_id}/cancel"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.kiteml.com/v1/training_runs/{run_id}/cancel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.kiteml.com/v1/training_runs/{run_id}/cancel",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.kiteml.com/v1/training_runs/{run_id}/cancel"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.kiteml.com/v1/training_runs/{run_id}/cancel")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kiteml.com/v1/training_runs/{run_id}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"cameras": {},
"completed_at": "2026-09-27T15:41:52.664301+00:00",
"config": {
"batch_size": 8,
"eval_enabled": false,
"save_freq": 1000,
"steps": 30000
},
"created_at": "2026-09-27T14:02:11.482913+00:00",
"dataset": {
"uri": "lerobot/svla_so101_pickplace"
},
"eval": {},
"group_id": "5f0c2e9a7b1d4c3e8f6a2b9d0c1e7f35",
"hardware_tier": "gcp_gpu_t4",
"id": "trn_01K65Z3N8Q4W2H7R9T6Y1B3C5D",
"metrics": {
"loss": 0.043,
"max_steps": 30000,
"step": 30000
},
"object": "training_run",
"output": {
"checkpoint_count": 30,
"hf_push_status": "ok",
"hf_repo_id": "your-hf-user/act-pickplace",
"hf_url": "https://huggingface.co/your-hf-user/act-pickplace",
"latest_checkpoint": {
"artifact_uri": "gs://example-bucket/jobs/7c1e9f0a2b3d4e5f8a9b0c1d2e3f4a5b/artifacts/lerobot/checkpoints/030000/pretrained_model/",
"created_at": "2026-09-27T15:38:40.120394+00:00",
"download_url": "/v1/training_runs/trn_01K65Z3N8Q4W2H7R9T6Y1B3C5D/checkpoints/30000/download",
"object": "training_checkpoint",
"step": 30000
}
},
"phase": "completed",
"policy": "act",
"progress": 1,
"robot": "so101_follower",
"started_at": "2026-09-27T14:02:13.107554+00:00",
"status": "succeeded",
"status_message": "Completed",
"tokens": {
"charged": 500,
"refunded": 0
},
"webhook_metadata": {
"ref": "nightly-42"
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}Cancel Training Run
Cancel a run and its GPU job. Terminal runs are a 409.
curl --request POST \
--url https://api.kiteml.com/v1/training_runs/{run_id}/cancel \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.kiteml.com/v1/training_runs/{run_id}/cancel"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.kiteml.com/v1/training_runs/{run_id}/cancel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.kiteml.com/v1/training_runs/{run_id}/cancel",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.kiteml.com/v1/training_runs/{run_id}/cancel"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.kiteml.com/v1/training_runs/{run_id}/cancel")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kiteml.com/v1/training_runs/{run_id}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"cameras": {},
"completed_at": "2026-09-27T15:41:52.664301+00:00",
"config": {
"batch_size": 8,
"eval_enabled": false,
"save_freq": 1000,
"steps": 30000
},
"created_at": "2026-09-27T14:02:11.482913+00:00",
"dataset": {
"uri": "lerobot/svla_so101_pickplace"
},
"eval": {},
"group_id": "5f0c2e9a7b1d4c3e8f6a2b9d0c1e7f35",
"hardware_tier": "gcp_gpu_t4",
"id": "trn_01K65Z3N8Q4W2H7R9T6Y1B3C5D",
"metrics": {
"loss": 0.043,
"max_steps": 30000,
"step": 30000
},
"object": "training_run",
"output": {
"checkpoint_count": 30,
"hf_push_status": "ok",
"hf_repo_id": "your-hf-user/act-pickplace",
"hf_url": "https://huggingface.co/your-hf-user/act-pickplace",
"latest_checkpoint": {
"artifact_uri": "gs://example-bucket/jobs/7c1e9f0a2b3d4e5f8a9b0c1d2e3f4a5b/artifacts/lerobot/checkpoints/030000/pretrained_model/",
"created_at": "2026-09-27T15:38:40.120394+00:00",
"download_url": "/v1/training_runs/trn_01K65Z3N8Q4W2H7R9T6Y1B3C5D/checkpoints/30000/download",
"object": "training_checkpoint",
"step": 30000
}
},
"phase": "completed",
"policy": "act",
"progress": 1,
"robot": "so101_follower",
"started_at": "2026-09-27T14:02:13.107554+00:00",
"status": "succeeded",
"status_message": "Completed",
"tokens": {
"charged": 500,
"refunded": 0
},
"webhook_metadata": {
"ref": "nightly-42"
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}Authorizations
A Kite API key (kite_...), from Platform API → Keys in the dashboard.
Headers
The dated contract your code was written against. Without it you get 2026-09-27; every response says which version served it.
2026-09-27 Path Parameters
Response
The run, canceled
One policy trained on one GPU.
trn_ + a time-ordered ULID
training_run "training_run"processing, succeeded, failed, canceled; an open set
Finer than status, e.g. provisioning, preparing, downloading_dataset, training, completed, failed, cancelled. Only GET /v1/training_runs/{id} reads it: null in list, create and cancel responses
phase in words, e.g. Provisioning GPU…
0 <= x <= 1Why, when failed
Show child attributes
Show child attributes
The LeRobot policy type (see GET /v1/training_policies)
The robot tag from create (a label only)
See GET /v1/hardware_tiers
Shared by the runs one create started, one per policy
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Live from the trainer on GET /v1/training_runs/{id}; elsewhere, the last values stored
Show child attributes
Show child attributes
Once the trainer has reported on evaluation (a finished run has); null in list, create and cancel responses
Show child attributes
Show child attributes
What the run has produced
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Echoed from create
When the GPU job was submitted
When it became succeeded, failed or canceled