Create Run
Train a policy. Only robot and task.objective are required; everything else has a verified default.
Returns 202 with one run per seed (sharing a group_id). A run trains, then packages its outputs: the policy
as ONNX and a checkpoint, the MuJoCo scene with a script that runs the policy in it, clips, and a report with a
verdict. Poll GET /v1/rl_runs/ or subscribe to rl_run.completed / rl_run.failed / rl_run.canceled.
Tokens are reserved now and settled by the minute when the run ends. Send an Idempotency-Key to make
retries safe.
curl --request POST \
--url https://api.kiteml.com/v1/rl_runs \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"budget": {
"iterations": 500,
"max_tokens": 400
},
"description": "Walk forward at a steady pace with a level body and alternating feet.",
"from": {
"policy": "4d574ce4c547"
},
"hardware_tier": "gcp_gpu_l4",
"metadata": {
"example": "rl_runs/walk.json"
},
"outputs": {
"formats": [
"onnx",
"pt",
"torchscript"
],
"videos": [
{
"command": {
"vx": 0.3
},
"seconds": 8
}
]
},
"robot": "open_duck_mini_v2",
"seeds": 1,
"task": {
"commands": {
"vx": [
0.2,
0.4
],
"vy": [
-0.05,
0.05
],
"yaw": [
-0.2,
0.2
]
},
"objective": "velocity"
},
"title": "Open Duck: steady walk (fine-tuned)"
}
'import requests
url = "https://api.kiteml.com/v1/rl_runs"
payload = {
"budget": {
"iterations": 500,
"max_tokens": 400
},
"description": "Walk forward at a steady pace with a level body and alternating feet.",
"from": { "policy": "4d574ce4c547" },
"hardware_tier": "gcp_gpu_l4",
"metadata": { "example": "rl_runs/walk.json" },
"outputs": {
"formats": ["onnx", "pt", "torchscript"],
"videos": [
{
"command": { "vx": 0.3 },
"seconds": 8
}
]
},
"robot": "open_duck_mini_v2",
"seeds": 1,
"task": {
"commands": {
"vx": [0.2, 0.4],
"vy": [-0.05, 0.05],
"yaw": [-0.2, 0.2]
},
"objective": "velocity"
},
"title": "Open Duck: steady walk (fine-tuned)"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
budget: {iterations: 500, max_tokens: 400},
description: 'Walk forward at a steady pace with a level body and alternating feet.',
from: {policy: '4d574ce4c547'},
hardware_tier: 'gcp_gpu_l4',
metadata: {example: 'rl_runs/walk.json'},
outputs: {
formats: ['onnx', 'pt', 'torchscript'],
videos: [{command: {vx: 0.3}, seconds: 8}]
},
robot: 'open_duck_mini_v2',
seeds: 1,
task: {
commands: {vx: [0.2, 0.4], vy: [-0.05, 0.05], yaw: [-0.2, 0.2]},
objective: 'velocity'
},
title: 'Open Duck: steady walk (fine-tuned)'
})
};
fetch('https://api.kiteml.com/v1/rl_runs', 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/rl_runs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'budget' => [
'iterations' => 500,
'max_tokens' => 400
],
'description' => 'Walk forward at a steady pace with a level body and alternating feet.',
'from' => [
'policy' => '4d574ce4c547'
],
'hardware_tier' => 'gcp_gpu_l4',
'metadata' => [
'example' => 'rl_runs/walk.json'
],
'outputs' => [
'formats' => [
'onnx',
'pt',
'torchscript'
],
'videos' => [
[
'command' => [
'vx' => 0.3
],
'seconds' => 8
]
]
],
'robot' => 'open_duck_mini_v2',
'seeds' => 1,
'task' => [
'commands' => [
'vx' => [
0.2,
0.4
],
'vy' => [
-0.05,
0.05
],
'yaw' => [
-0.2,
0.2
]
],
'objective' => 'velocity'
],
'title' => 'Open Duck: steady walk (fine-tuned)'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.kiteml.com/v1/rl_runs"
payload := strings.NewReader("{\n \"budget\": {\n \"iterations\": 500,\n \"max_tokens\": 400\n },\n \"description\": \"Walk forward at a steady pace with a level body and alternating feet.\",\n \"from\": {\n \"policy\": \"4d574ce4c547\"\n },\n \"hardware_tier\": \"gcp_gpu_l4\",\n \"metadata\": {\n \"example\": \"rl_runs/walk.json\"\n },\n \"outputs\": {\n \"formats\": [\n \"onnx\",\n \"pt\",\n \"torchscript\"\n ],\n \"videos\": [\n {\n \"command\": {\n \"vx\": 0.3\n },\n \"seconds\": 8\n }\n ]\n },\n \"robot\": \"open_duck_mini_v2\",\n \"seeds\": 1,\n \"task\": {\n \"commands\": {\n \"vx\": [\n 0.2,\n 0.4\n ],\n \"vy\": [\n -0.05,\n 0.05\n ],\n \"yaw\": [\n -0.2,\n 0.2\n ]\n },\n \"objective\": \"velocity\"\n },\n \"title\": \"Open Duck: steady walk (fine-tuned)\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
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/rl_runs")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"budget\": {\n \"iterations\": 500,\n \"max_tokens\": 400\n },\n \"description\": \"Walk forward at a steady pace with a level body and alternating feet.\",\n \"from\": {\n \"policy\": \"4d574ce4c547\"\n },\n \"hardware_tier\": \"gcp_gpu_l4\",\n \"metadata\": {\n \"example\": \"rl_runs/walk.json\"\n },\n \"outputs\": {\n \"formats\": [\n \"onnx\",\n \"pt\",\n \"torchscript\"\n ],\n \"videos\": [\n {\n \"command\": {\n \"vx\": 0.3\n },\n \"seconds\": 8\n }\n ]\n },\n \"robot\": \"open_duck_mini_v2\",\n \"seeds\": 1,\n \"task\": {\n \"commands\": {\n \"vx\": [\n 0.2,\n 0.4\n ],\n \"vy\": [\n -0.05,\n 0.05\n ],\n \"yaw\": [\n -0.2,\n 0.2\n ]\n },\n \"objective\": \"velocity\"\n },\n \"title\": \"Open Duck: steady walk (fine-tuned)\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kiteml.com/v1/rl_runs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"budget\": {\n \"iterations\": 500,\n \"max_tokens\": 400\n },\n \"description\": \"Walk forward at a steady pace with a level body and alternating feet.\",\n \"from\": {\n \"policy\": \"4d574ce4c547\"\n },\n \"hardware_tier\": \"gcp_gpu_l4\",\n \"metadata\": {\n \"example\": \"rl_runs/walk.json\"\n },\n \"outputs\": {\n \"formats\": [\n \"onnx\",\n \"pt\",\n \"torchscript\"\n ],\n \"videos\": [\n {\n \"command\": {\n \"vx\": 0.3\n },\n \"seconds\": 8\n }\n ]\n },\n \"robot\": \"open_duck_mini_v2\",\n \"seeds\": 1,\n \"task\": {\n \"commands\": {\n \"vx\": [\n 0.2,\n 0.4\n ],\n \"vy\": [\n -0.05,\n 0.05\n ],\n \"yaw\": [\n -0.2,\n 0.2\n ]\n },\n \"objective\": \"velocity\"\n },\n \"title\": \"Open Duck: steady walk (fine-tuned)\"\n}"
response = http.request(request)
puts response.read_body{
"data": [
{
"budget": {
"iterations": 500,
"max_tokens": 400,
"num_envs": 2048
},
"created_at": "2026-09-28T19:15:36.753577Z",
"description": "Walk forward at a steady pace with a level body and alternating feet.",
"engine": "2026-09-28",
"from": {
"mode": "fork",
"policy": "4d574ce4c547"
},
"group_id": "rlg_01M3MQ39HV4YNTWNNY2GHM55VC",
"hardware_tier": "gcp_gpu_l4",
"id": "rlr_01M3MQ39HVAEBQ3F64K6JDF9XR",
"metadata": {
"example": "rl_runs/walk.json"
},
"metrics": {
"terms": {}
},
"object": "rl_run",
"outputs": {
"formats": [
"onnx",
"pt",
"torchscript"
],
"videos": [
{
"command": {
"vx": 0.3
},
"seconds": 8
}
]
},
"progress": 0,
"robot": "open_duck_mini_v2",
"seed": 0,
"status": "queued",
"status_message": "waiting for a machine",
"task": {
"commands": {
"vx": [
0.2,
0.4
],
"vy": [
-0.05,
0.05
],
"yaw": [
-0.2,
0.2
]
},
"objective": "velocity",
"params": {},
"scene": {
"items": []
}
},
"title": "Open Duck: steady walk (fine-tuned)",
"tokens": {
"charged": 0,
"refunded": 0,
"reserved": 167
},
"visibility": "private"
}
],
"has_more": false,
"object": "list"
}{
"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": {}
}
}{
"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
255The dated contract your code was written against. Without it you get 2026-09-27; every response says which version served it.
2026-09-27 Body
Train a policy. Only robot and task.objective are required.
See GET /v1/rl_runs/catalog
What to learn.
Show child attributes
Show child attributes
The dated trainer to use (default: the latest, or the parent's for a fork or continue of your run). A run keeps its engine
Show child attributes
Show child attributes
A count (1-5) or explicit seeds: one run per seed, sharing a group_id
Start from another policy instead of from scratch.
Show child attributes
Show child attributes
Extras beyond what every run produces (ONNX, the checkpoint, the scene, one clip, the report).
Show child attributes
Show child attributes
See GET /v1/rl_runs/catalog (default gcp_gpu_l4)
public lists the run in the policy catalog once it finishes with a pass verdict
private, public 120What the behavior should look like; the report's judge compares the clip against it
2000Your labels, echoed on the run
Show child attributes
Show child attributes
Echoed on the run and its events
curl --request POST \
--url https://api.kiteml.com/v1/rl_runs \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"budget": {
"iterations": 500,
"max_tokens": 400
},
"description": "Walk forward at a steady pace with a level body and alternating feet.",
"from": {
"policy": "4d574ce4c547"
},
"hardware_tier": "gcp_gpu_l4",
"metadata": {
"example": "rl_runs/walk.json"
},
"outputs": {
"formats": [
"onnx",
"pt",
"torchscript"
],
"videos": [
{
"command": {
"vx": 0.3
},
"seconds": 8
}
]
},
"robot": "open_duck_mini_v2",
"seeds": 1,
"task": {
"commands": {
"vx": [
0.2,
0.4
],
"vy": [
-0.05,
0.05
],
"yaw": [
-0.2,
0.2
]
},
"objective": "velocity"
},
"title": "Open Duck: steady walk (fine-tuned)"
}
'import requests
url = "https://api.kiteml.com/v1/rl_runs"
payload = {
"budget": {
"iterations": 500,
"max_tokens": 400
},
"description": "Walk forward at a steady pace with a level body and alternating feet.",
"from": { "policy": "4d574ce4c547" },
"hardware_tier": "gcp_gpu_l4",
"metadata": { "example": "rl_runs/walk.json" },
"outputs": {
"formats": ["onnx", "pt", "torchscript"],
"videos": [
{
"command": { "vx": 0.3 },
"seconds": 8
}
]
},
"robot": "open_duck_mini_v2",
"seeds": 1,
"task": {
"commands": {
"vx": [0.2, 0.4],
"vy": [-0.05, 0.05],
"yaw": [-0.2, 0.2]
},
"objective": "velocity"
},
"title": "Open Duck: steady walk (fine-tuned)"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
budget: {iterations: 500, max_tokens: 400},
description: 'Walk forward at a steady pace with a level body and alternating feet.',
from: {policy: '4d574ce4c547'},
hardware_tier: 'gcp_gpu_l4',
metadata: {example: 'rl_runs/walk.json'},
outputs: {
formats: ['onnx', 'pt', 'torchscript'],
videos: [{command: {vx: 0.3}, seconds: 8}]
},
robot: 'open_duck_mini_v2',
seeds: 1,
task: {
commands: {vx: [0.2, 0.4], vy: [-0.05, 0.05], yaw: [-0.2, 0.2]},
objective: 'velocity'
},
title: 'Open Duck: steady walk (fine-tuned)'
})
};
fetch('https://api.kiteml.com/v1/rl_runs', 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/rl_runs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'budget' => [
'iterations' => 500,
'max_tokens' => 400
],
'description' => 'Walk forward at a steady pace with a level body and alternating feet.',
'from' => [
'policy' => '4d574ce4c547'
],
'hardware_tier' => 'gcp_gpu_l4',
'metadata' => [
'example' => 'rl_runs/walk.json'
],
'outputs' => [
'formats' => [
'onnx',
'pt',
'torchscript'
],
'videos' => [
[
'command' => [
'vx' => 0.3
],
'seconds' => 8
]
]
],
'robot' => 'open_duck_mini_v2',
'seeds' => 1,
'task' => [
'commands' => [
'vx' => [
0.2,
0.4
],
'vy' => [
-0.05,
0.05
],
'yaw' => [
-0.2,
0.2
]
],
'objective' => 'velocity'
],
'title' => 'Open Duck: steady walk (fine-tuned)'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.kiteml.com/v1/rl_runs"
payload := strings.NewReader("{\n \"budget\": {\n \"iterations\": 500,\n \"max_tokens\": 400\n },\n \"description\": \"Walk forward at a steady pace with a level body and alternating feet.\",\n \"from\": {\n \"policy\": \"4d574ce4c547\"\n },\n \"hardware_tier\": \"gcp_gpu_l4\",\n \"metadata\": {\n \"example\": \"rl_runs/walk.json\"\n },\n \"outputs\": {\n \"formats\": [\n \"onnx\",\n \"pt\",\n \"torchscript\"\n ],\n \"videos\": [\n {\n \"command\": {\n \"vx\": 0.3\n },\n \"seconds\": 8\n }\n ]\n },\n \"robot\": \"open_duck_mini_v2\",\n \"seeds\": 1,\n \"task\": {\n \"commands\": {\n \"vx\": [\n 0.2,\n 0.4\n ],\n \"vy\": [\n -0.05,\n 0.05\n ],\n \"yaw\": [\n -0.2,\n 0.2\n ]\n },\n \"objective\": \"velocity\"\n },\n \"title\": \"Open Duck: steady walk (fine-tuned)\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
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/rl_runs")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"budget\": {\n \"iterations\": 500,\n \"max_tokens\": 400\n },\n \"description\": \"Walk forward at a steady pace with a level body and alternating feet.\",\n \"from\": {\n \"policy\": \"4d574ce4c547\"\n },\n \"hardware_tier\": \"gcp_gpu_l4\",\n \"metadata\": {\n \"example\": \"rl_runs/walk.json\"\n },\n \"outputs\": {\n \"formats\": [\n \"onnx\",\n \"pt\",\n \"torchscript\"\n ],\n \"videos\": [\n {\n \"command\": {\n \"vx\": 0.3\n },\n \"seconds\": 8\n }\n ]\n },\n \"robot\": \"open_duck_mini_v2\",\n \"seeds\": 1,\n \"task\": {\n \"commands\": {\n \"vx\": [\n 0.2,\n 0.4\n ],\n \"vy\": [\n -0.05,\n 0.05\n ],\n \"yaw\": [\n -0.2,\n 0.2\n ]\n },\n \"objective\": \"velocity\"\n },\n \"title\": \"Open Duck: steady walk (fine-tuned)\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kiteml.com/v1/rl_runs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"budget\": {\n \"iterations\": 500,\n \"max_tokens\": 400\n },\n \"description\": \"Walk forward at a steady pace with a level body and alternating feet.\",\n \"from\": {\n \"policy\": \"4d574ce4c547\"\n },\n \"hardware_tier\": \"gcp_gpu_l4\",\n \"metadata\": {\n \"example\": \"rl_runs/walk.json\"\n },\n \"outputs\": {\n \"formats\": [\n \"onnx\",\n \"pt\",\n \"torchscript\"\n ],\n \"videos\": [\n {\n \"command\": {\n \"vx\": 0.3\n },\n \"seconds\": 8\n }\n ]\n },\n \"robot\": \"open_duck_mini_v2\",\n \"seeds\": 1,\n \"task\": {\n \"commands\": {\n \"vx\": [\n 0.2,\n 0.4\n ],\n \"vy\": [\n -0.05,\n 0.05\n ],\n \"yaw\": [\n -0.2,\n 0.2\n ]\n },\n \"objective\": \"velocity\"\n },\n \"title\": \"Open Duck: steady walk (fine-tuned)\"\n}"
response = http.request(request)
puts response.read_body{
"data": [
{
"budget": {
"iterations": 500,
"max_tokens": 400,
"num_envs": 2048
},
"created_at": "2026-09-28T19:15:36.753577Z",
"description": "Walk forward at a steady pace with a level body and alternating feet.",
"engine": "2026-09-28",
"from": {
"mode": "fork",
"policy": "4d574ce4c547"
},
"group_id": "rlg_01M3MQ39HV4YNTWNNY2GHM55VC",
"hardware_tier": "gcp_gpu_l4",
"id": "rlr_01M3MQ39HVAEBQ3F64K6JDF9XR",
"metadata": {
"example": "rl_runs/walk.json"
},
"metrics": {
"terms": {}
},
"object": "rl_run",
"outputs": {
"formats": [
"onnx",
"pt",
"torchscript"
],
"videos": [
{
"command": {
"vx": 0.3
},
"seconds": 8
}
]
},
"progress": 0,
"robot": "open_duck_mini_v2",
"seed": 0,
"status": "queued",
"status_message": "waiting for a machine",
"task": {
"commands": {
"vx": [
0.2,
0.4
],
"vy": [
-0.05,
0.05
],
"yaw": [
-0.2,
0.2
]
},
"objective": "velocity",
"params": {},
"scene": {
"items": []
}
},
"title": "Open Duck: steady walk (fine-tuned)",
"tokens": {
"charged": 0,
"refunded": 0,
"reserved": 167
},
"visibility": "private"
}
],
"has_more": false,
"object": "list"
}{
"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": {}
}
}{
"error": {
"type": "<string>",
"code": "<string>",
"message": "<string>",
"param": "<string>",
"request_id": "<string>",
"details": {}
}
}