curl --request POST \
--url https://api.example.com/api/v1/runs \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"workflow_version_id": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"target": {
"kind": "git",
"repo": "acme/my-app",
"branch": "feature/foo",
"tag": "v1.2.3",
"sha": "<string>"
},
"args": {
"model": "<string>",
"provider": "<string>",
"inputs": {},
"labels": {},
"dry_run": true,
"auto_approve": true,
"preserve_sandbox": true
},
"environment_id": "<string>",
"parent_id": "<string>",
"title": "<string>",
"goal": "<string>"
}
'import requests
url = "https://api.example.com/api/v1/runs"
payload = {
"workflow_version_id": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"target": {
"kind": "git",
"repo": "acme/my-app",
"branch": "feature/foo",
"tag": "v1.2.3",
"sha": "<string>"
},
"args": {
"model": "<string>",
"provider": "<string>",
"inputs": {},
"labels": {},
"dry_run": True,
"auto_approve": True,
"preserve_sandbox": True
},
"environment_id": "<string>",
"parent_id": "<string>",
"title": "<string>",
"goal": "<string>"
}
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({
workflow_version_id: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
target: {
kind: 'git',
repo: 'acme/my-app',
branch: 'feature/foo',
tag: 'v1.2.3',
sha: '<string>'
},
args: {
model: '<string>',
provider: '<string>',
inputs: {},
labels: {},
dry_run: true,
auto_approve: true,
preserve_sandbox: true
},
environment_id: '<string>',
parent_id: '<string>',
title: '<string>',
goal: '<string>'
})
};
fetch('https://api.example.com/api/v1/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.example.com/api/v1/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([
'workflow_version_id' => '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
'target' => [
'kind' => 'git',
'repo' => 'acme/my-app',
'branch' => 'feature/foo',
'tag' => 'v1.2.3',
'sha' => '<string>'
],
'args' => [
'model' => '<string>',
'provider' => '<string>',
'inputs' => [
],
'labels' => [
],
'dry_run' => true,
'auto_approve' => true,
'preserve_sandbox' => true
],
'environment_id' => '<string>',
'parent_id' => '<string>',
'title' => '<string>',
'goal' => '<string>'
]),
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.example.com/api/v1/runs"
payload := strings.NewReader("{\n \"workflow_version_id\": \"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\n \"target\": {\n \"kind\": \"git\",\n \"repo\": \"acme/my-app\",\n \"branch\": \"feature/foo\",\n \"tag\": \"v1.2.3\",\n \"sha\": \"<string>\"\n },\n \"args\": {\n \"model\": \"<string>\",\n \"provider\": \"<string>\",\n \"inputs\": {},\n \"labels\": {},\n \"dry_run\": true,\n \"auto_approve\": true,\n \"preserve_sandbox\": true\n },\n \"environment_id\": \"<string>\",\n \"parent_id\": \"<string>\",\n \"title\": \"<string>\",\n \"goal\": \"<string>\"\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.example.com/api/v1/runs")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"workflow_version_id\": \"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\n \"target\": {\n \"kind\": \"git\",\n \"repo\": \"acme/my-app\",\n \"branch\": \"feature/foo\",\n \"tag\": \"v1.2.3\",\n \"sha\": \"<string>\"\n },\n \"args\": {\n \"model\": \"<string>\",\n \"provider\": \"<string>\",\n \"inputs\": {},\n \"labels\": {},\n \"dry_run\": true,\n \"auto_approve\": true,\n \"preserve_sandbox\": true\n },\n \"environment_id\": \"<string>\",\n \"parent_id\": \"<string>\",\n \"title\": \"<string>\",\n \"goal\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/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 \"workflow_version_id\": \"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\n \"target\": {\n \"kind\": \"git\",\n \"repo\": \"acme/my-app\",\n \"branch\": \"feature/foo\",\n \"tag\": \"v1.2.3\",\n \"sha\": \"<string>\"\n },\n \"args\": {\n \"model\": \"<string>\",\n \"provider\": \"<string>\",\n \"inputs\": {},\n \"labels\": {},\n \"dry_run\": true,\n \"auto_approve\": true,\n \"preserve_sandbox\": true\n },\n \"environment_id\": \"<string>\",\n \"parent_id\": \"<string>\",\n \"title\": \"<string>\",\n \"goal\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"children_count": 1,
"title": "<string>",
"goal": "<string>",
"workflow": {
"slug": "<string>",
"name": "<string>",
"graph_name": "<string>",
"node_count": 123,
"edge_count": 123
},
"automation": {
"id": "<string>",
"name": "<string>",
"trigger_id": "<string>",
"workflow_source": {
"repo": "<string>",
"branch": "<string>",
"resolved_sha": "<string>",
"tag": "<string>",
"sha": "<string>"
}
},
"repository": {
"name": "fabro-sh/fabro",
"origin_url": "https://github.com/fabro-sh/fabro.git",
"provider": "github"
},
"created_by": {
"kind": "user",
"identity": {
"issuer": "<string>",
"subject": "<string>"
},
"login": "<string>",
"auth_method": "github",
"avatar_url": "<string>"
},
"origin": {
"kind": "api"
},
"labels": {},
"lifecycle": {
"status": {
"kind": "submitted"
},
"approval": {
"state": "pending",
"requested_at": "2023-11-07T05:31:56Z",
"decided_at": "2023-11-07T05:31:56Z",
"denial_reason": "<string>"
},
"pending_control": "cancel",
"queue_position": 123,
"error": {
"message": "Stage 'apply-changes' exceeded maximum retries."
},
"archived": true,
"archived_at": "2023-11-07T05:31:56Z"
},
"sandbox": {
"kind": "planned",
"plan": {
"provider": "docker",
"image": "<string>",
"snapshot": "<string>"
},
"instance": {
"provider": "docker",
"runtime": {
"id": "<string>",
"working_directory": "<string>",
"repo_cloned": true,
"clone_origin_url": "<string>",
"clone_branch": "<string>",
"workspace_root": "<string>",
"repos_root": "<string>",
"primary_repo_path": "<string>",
"primary_repo_link": "<string>"
},
"image": "<string>",
"snapshot": "<string>",
"ready_duration_ms": 1,
"retained": true
},
"failure": {
"provider": "<string>",
"error": "<string>",
"causes": [
"<string>"
],
"duration_ms": 1
}
},
"models": [
{
"provider": "<string>",
"name": "<string>"
}
],
"source_directory": "<string>",
"timestamps": {
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"last_event_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z"
},
"timing": {
"wall_time_ms": 420000,
"inference_time_ms": 120000,
"tool_time_ms": 60000,
"active_time_ms": 180000
},
"usage": {
"tokens": {
"input": 0,
"output": 0,
"reasoning": 0,
"cache_read": 0,
"cache_write": 0
},
"cost": {
"usd_micros": 1,
"source": "catalog"
}
},
"size": "XS",
"ask_fabro": {
"available": true,
"unavailable_reason": "no_sandbox",
"default_model": "<string>"
},
"diff": {
"files_changed": 42,
"additions": 567,
"deletions": 234
},
"pull_request": {
"owner": "fabro-sh",
"repo": "fabro",
"number": 123,
"html_url": "https://github.com/fabro-sh/fabro/pull/123"
},
"current_question": {
"text": "Accept or push for another round?"
},
"superseded_by": "<string>",
"retried_from": "<string>",
"links": {
"web": "<string>"
},
"parent_id": "<string>"
}{
"errors": [
{
"status": "404",
"title": "Not Found",
"detail": "Run not found.",
"code": "access_token_expired",
"request_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"meta": {}
}
],
"request_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"leftover_env_keys": [
"<string>"
],
"removed_env_keys": [
"<string>"
]
}Create Run
Creates a new workflow run in submitted status from an immutable workflow-version intent. Creation does not start or schedule the run.
Failures return the standard error body. The endpoint responds 404 (workflow_version_not_found, environment_not_found), 422 (run_intent_invalid, target_invalid, target_environment_unsupported, pull_request_environment_unsupported, workflow_version_unusable, run_compile_invalid), 503 (integration_unavailable), or 500 (workflow_version_store_error, credential_store_error, variable_store_error, run_persistence_failed).
curl --request POST \
--url https://api.example.com/api/v1/runs \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"workflow_version_id": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"target": {
"kind": "git",
"repo": "acme/my-app",
"branch": "feature/foo",
"tag": "v1.2.3",
"sha": "<string>"
},
"args": {
"model": "<string>",
"provider": "<string>",
"inputs": {},
"labels": {},
"dry_run": true,
"auto_approve": true,
"preserve_sandbox": true
},
"environment_id": "<string>",
"parent_id": "<string>",
"title": "<string>",
"goal": "<string>"
}
'import requests
url = "https://api.example.com/api/v1/runs"
payload = {
"workflow_version_id": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"target": {
"kind": "git",
"repo": "acme/my-app",
"branch": "feature/foo",
"tag": "v1.2.3",
"sha": "<string>"
},
"args": {
"model": "<string>",
"provider": "<string>",
"inputs": {},
"labels": {},
"dry_run": True,
"auto_approve": True,
"preserve_sandbox": True
},
"environment_id": "<string>",
"parent_id": "<string>",
"title": "<string>",
"goal": "<string>"
}
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({
workflow_version_id: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
target: {
kind: 'git',
repo: 'acme/my-app',
branch: 'feature/foo',
tag: 'v1.2.3',
sha: '<string>'
},
args: {
model: '<string>',
provider: '<string>',
inputs: {},
labels: {},
dry_run: true,
auto_approve: true,
preserve_sandbox: true
},
environment_id: '<string>',
parent_id: '<string>',
title: '<string>',
goal: '<string>'
})
};
fetch('https://api.example.com/api/v1/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.example.com/api/v1/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([
'workflow_version_id' => '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
'target' => [
'kind' => 'git',
'repo' => 'acme/my-app',
'branch' => 'feature/foo',
'tag' => 'v1.2.3',
'sha' => '<string>'
],
'args' => [
'model' => '<string>',
'provider' => '<string>',
'inputs' => [
],
'labels' => [
],
'dry_run' => true,
'auto_approve' => true,
'preserve_sandbox' => true
],
'environment_id' => '<string>',
'parent_id' => '<string>',
'title' => '<string>',
'goal' => '<string>'
]),
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.example.com/api/v1/runs"
payload := strings.NewReader("{\n \"workflow_version_id\": \"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\n \"target\": {\n \"kind\": \"git\",\n \"repo\": \"acme/my-app\",\n \"branch\": \"feature/foo\",\n \"tag\": \"v1.2.3\",\n \"sha\": \"<string>\"\n },\n \"args\": {\n \"model\": \"<string>\",\n \"provider\": \"<string>\",\n \"inputs\": {},\n \"labels\": {},\n \"dry_run\": true,\n \"auto_approve\": true,\n \"preserve_sandbox\": true\n },\n \"environment_id\": \"<string>\",\n \"parent_id\": \"<string>\",\n \"title\": \"<string>\",\n \"goal\": \"<string>\"\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.example.com/api/v1/runs")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"workflow_version_id\": \"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\n \"target\": {\n \"kind\": \"git\",\n \"repo\": \"acme/my-app\",\n \"branch\": \"feature/foo\",\n \"tag\": \"v1.2.3\",\n \"sha\": \"<string>\"\n },\n \"args\": {\n \"model\": \"<string>\",\n \"provider\": \"<string>\",\n \"inputs\": {},\n \"labels\": {},\n \"dry_run\": true,\n \"auto_approve\": true,\n \"preserve_sandbox\": true\n },\n \"environment_id\": \"<string>\",\n \"parent_id\": \"<string>\",\n \"title\": \"<string>\",\n \"goal\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/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 \"workflow_version_id\": \"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\n \"target\": {\n \"kind\": \"git\",\n \"repo\": \"acme/my-app\",\n \"branch\": \"feature/foo\",\n \"tag\": \"v1.2.3\",\n \"sha\": \"<string>\"\n },\n \"args\": {\n \"model\": \"<string>\",\n \"provider\": \"<string>\",\n \"inputs\": {},\n \"labels\": {},\n \"dry_run\": true,\n \"auto_approve\": true,\n \"preserve_sandbox\": true\n },\n \"environment_id\": \"<string>\",\n \"parent_id\": \"<string>\",\n \"title\": \"<string>\",\n \"goal\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"children_count": 1,
"title": "<string>",
"goal": "<string>",
"workflow": {
"slug": "<string>",
"name": "<string>",
"graph_name": "<string>",
"node_count": 123,
"edge_count": 123
},
"automation": {
"id": "<string>",
"name": "<string>",
"trigger_id": "<string>",
"workflow_source": {
"repo": "<string>",
"branch": "<string>",
"resolved_sha": "<string>",
"tag": "<string>",
"sha": "<string>"
}
},
"repository": {
"name": "fabro-sh/fabro",
"origin_url": "https://github.com/fabro-sh/fabro.git",
"provider": "github"
},
"created_by": {
"kind": "user",
"identity": {
"issuer": "<string>",
"subject": "<string>"
},
"login": "<string>",
"auth_method": "github",
"avatar_url": "<string>"
},
"origin": {
"kind": "api"
},
"labels": {},
"lifecycle": {
"status": {
"kind": "submitted"
},
"approval": {
"state": "pending",
"requested_at": "2023-11-07T05:31:56Z",
"decided_at": "2023-11-07T05:31:56Z",
"denial_reason": "<string>"
},
"pending_control": "cancel",
"queue_position": 123,
"error": {
"message": "Stage 'apply-changes' exceeded maximum retries."
},
"archived": true,
"archived_at": "2023-11-07T05:31:56Z"
},
"sandbox": {
"kind": "planned",
"plan": {
"provider": "docker",
"image": "<string>",
"snapshot": "<string>"
},
"instance": {
"provider": "docker",
"runtime": {
"id": "<string>",
"working_directory": "<string>",
"repo_cloned": true,
"clone_origin_url": "<string>",
"clone_branch": "<string>",
"workspace_root": "<string>",
"repos_root": "<string>",
"primary_repo_path": "<string>",
"primary_repo_link": "<string>"
},
"image": "<string>",
"snapshot": "<string>",
"ready_duration_ms": 1,
"retained": true
},
"failure": {
"provider": "<string>",
"error": "<string>",
"causes": [
"<string>"
],
"duration_ms": 1
}
},
"models": [
{
"provider": "<string>",
"name": "<string>"
}
],
"source_directory": "<string>",
"timestamps": {
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"last_event_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z"
},
"timing": {
"wall_time_ms": 420000,
"inference_time_ms": 120000,
"tool_time_ms": 60000,
"active_time_ms": 180000
},
"usage": {
"tokens": {
"input": 0,
"output": 0,
"reasoning": 0,
"cache_read": 0,
"cache_write": 0
},
"cost": {
"usd_micros": 1,
"source": "catalog"
}
},
"size": "XS",
"ask_fabro": {
"available": true,
"unavailable_reason": "no_sandbox",
"default_model": "<string>"
},
"diff": {
"files_changed": 42,
"additions": 567,
"deletions": 234
},
"pull_request": {
"owner": "fabro-sh",
"repo": "fabro",
"number": 123,
"html_url": "https://github.com/fabro-sh/fabro/pull/123"
},
"current_question": {
"text": "Accept or push for another round?"
},
"superseded_by": "<string>",
"retried_from": "<string>",
"links": {
"web": "<string>"
},
"parent_id": "<string>"
}{
"errors": [
{
"status": "404",
"title": "Not Found",
"detail": "Run not found.",
"code": "access_token_expired",
"request_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"meta": {}
}
],
"request_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"leftover_env_keys": [
"<string>"
],
"removed_env_keys": [
"<string>"
]
}Authorizations
Raw dev token passed as Authorization: Bearer fabro_dev_... when server.auth.methods includes dev-token.
Body
A request to create, but not start, one run from an immutable workflow version and an explicit workspace target.
SHA-256 identity of validated canonical workflow-version bytes. Hex input is case-insensitive; Fabro emits the canonical lowercase form.
^[0-9A-Fa-f]{64}$"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
Workspace content and location requested for a run.
- Option 1
- Option 2
- Option 3
Show child attributes
Show child attributes
Structured run overrides accepted by workflow-version creation.
Show child attributes
Show child attributes
Server environment catalog ID. Omission selects default.
Optional orchestration parent run ID.
Optional explicit run title, normalized by the server.
100Optional inline goal override.
Response
Run created
Canonical public run shape.
Number of runs currently linked to this run as their orchestration parent.
x >= 0Show child attributes
Show child attributes
Show child attributes
Show child attributes
Durable repository metadata for a run.
Show child attributes
Show child attributes
- Option 1
- Option 2
- Option 3
- Option 4
- Option 5
- Option 6
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Sandbox lifecycle record for a run. A run can have a requested sandbox plan before it has an initialized sandbox instance.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Run-level timing rollup. Wall time is the run's clock duration; active timing sums work across stage visits.
Show child attributes
Show child attributes
The run's usage summed across every stage visit so far: the conclusion's total once the run ended, else the sum of the stages'.
Show child attributes
Show child attributes
Run size bucket derived from the run's current cost.
XS, S, M, L, XL Readiness and defaults for starting an Ask Fabro session on this run.
Show child attributes
Show child attributes
Cheap aggregate file and line counts for a run diff.
Show child attributes
Show child attributes
Minimal GitHub pull request link associated with a run.
Show child attributes
Show child attributes
A pending human-in-the-loop question summary.
Show child attributes
Show child attributes
Run ID that superseded this run via rewind, if any.
Source run ID when this run was created by manual retry.
Show child attributes
Show child attributes
Current orchestration parent run ID, if linked.