Create runs

Starts a run: name exactly one of template, flow or graph, with the input its inputs schema asks for.

POST /v1/studio/runs

Addresshttps://api.hanzo.ai/v1/studio/runs
MethodPOST
Operationpost_studio_runs
AuthAuthorization: Bearer $HANZO_API_KEY

Starts a run: name exactly one of template, flow or graph, with the input its inputs schema asks for. The run is checked, priced and its estimate reserved against your org's wallet, then queued; the answer is the run at queued. Follow it on GET /v1/studio/runs/{id}/events.

parent makes this run the next version of that run: it takes the parent's graph and input, overlaid by what this request states. Send Idempotency-Key to make a retried request start one run, not two. 402 when the wallet cannot cover the estimate; 422 when the graph or input does not validate.

Request

17 fields, body application/json (required).

FieldInTypeRequiredDescription
Idempotency-Keyheaderstring—
brandbodystring—Brand is a brand id; its tokens are brand.* in the graph.
flowbodystring—Flow is a flow id.
graphbodystudio.Graph—
graph.stepsbodystudio.Spec[]—Steps are the graph's steps, 1 to 64 of them.
graph.steps[].eachbodystring—Each fans the step out: a {{path}} naming an array, run once per item (at most 64), its outputs the items' outputs in order.
graph.steps[].idbodystring—ID names the step within its graph: a lowercase letter, then up to 31 lowercase letters, digits or underscores.
graph.steps[].opbodystring—Op is what the step does: chat, image.generate, image.edit, voice.speak, music.generate, video.generate, model.generate, studio.render, render.html, render.document, render.slides, render.composition or video.edit.
graph.steps[].titlebodystring—Title is what a person sees for the step.
graph.steps[].withbodyobject—With are the op's parameters.
graph.steps[].with.*bodyany—
inputbodyobject—Input are the values the inputs schema asks for.
input.*bodyany—
parentbodystring—Parent makes this run the next version of that run.
sharedbodyboolean—
templatebodystring—Template is a template id.
titlebodystring—

Response

StatusBodyMeaning
201studio.Runcreated
defaultproblem-detailsrefused

201 body — 77 fields.

FieldInTypeAlwaysDescription
brandbodystring—
charged_centsbodyinteger (int64)—ChargedCents is what the finished steps cost; final once the run ends.
createdbodystring—
creatorbodystring—
errorbodystudio.Problem—
error.codebodystring—
error.detailbodystring—
error.statusbodyinteger (int64)—
error.titlebodystring—
error.typebodystring—
estimate_centsbodyinteger (int64)—EstimateCents is what was reserved when the run started.
finishedbodystring—
flowbodystring—
graphbodystudio.Graph—
graph.stepsbodystudio.Spec[]—Steps are the graph's steps, 1 to 64 of them.
graph.steps[].eachbodystring—Each fans the step out: a {{path}} naming an array, run once per item (at most 64), its outputs the items' outputs in order.
graph.steps[].idbodystring—ID names the step within its graph: a lowercase letter, then up to 31 lowercase letters, digits or underscores.
graph.steps[].opbodystring—Op is what the step does: chat, image.generate, image.edit, voice.speak, music.generate, video.generate, model.generate, studio.render, render.html, render.document, render.slides, render.composition or video.edit.
graph.steps[].titlebodystring—Title is what a person sees for the step.
graph.steps[].withbodyobject—With are the op's parameters.
graph.steps[].with.*bodyany—
idbodystring—
inputbodyobject—Input is what the run was given, as its inputs schema reads it.
input.*bodyany—
kindbodystring—
orgbodystring—
outputsbodystudio.Item[]—Outputs are the Library items the run made, the final steps' first.
outputs[].bytesbodyinteger (int64)—
outputs[].createdbodystring—
outputs[].downloadbodystring—
outputs[].expiresbodystring—
outputs[].heightbodyinteger (int64)—
outputs[].idbodystring—
outputs[].kindbodystring—
outputs[].mimebodystring—
outputs[].minebodyboolean—
outputs[].namebodystring—
outputs[].originbodystring—
outputs[].ownerbodystring—
outputs[].pagesbodyinteger (int64)—
outputs[].previewbodystring—
outputs[].refbodystring—
outputs[].secondsbodynumber (double)—
outputs[].sharedbodyboolean—
outputs[].sourcebodystring—
outputs[].urlbodystring—URL opens the file inline; Download saves it; Preview is its still.
outputs[].widthbodyinteger (int64)—
parentbodystring—
rootbodystring—Root is the first version's id; equal to id on version 1.
sharedbodyboolean—
startedbodystring—
statusbodystring—
stepsbodystudio.Step[]—
steps[].attemptbodyinteger (int64)—Attempt is how many times the step has started.
steps[].cost_centsbodyinteger (int64)—
steps[].errorbodystudio.Problem—
steps[].error.codebodystring—
steps[].error.detailbodystring—
steps[].error.statusbodyinteger (int64)—
steps[].error.titlebodystring—
steps[].error.typebodystring—
steps[].executorbodystring—Executor is where the step runs: gateway, studio.render, render or flow.run.
steps[].finishedbodystring—
steps[].idbodystring—
steps[].itemsbodyinteger (int64)—Items is how many items a step with each fanned out to.
steps[].messagebodystring—Message is what the step is doing now, for a person.
steps[].opbodystring—
steps[].outputsbodystring[]—Outputs are the Library item ids the step made.
steps[].progressbodynumber (double)—
steps[].startedbodystring—
steps[].statusbodystring—Status is pending, queued, running, succeeded, failed, canceled or skipped.
steps[].textbodystring—
steps[].titlebodystring—
templatebodystring—
textbodystring—Text is the last chat step's text, when the run's product is words.
titlebodystring—
versionbodyinteger (int64)—

Failure carries the platform error shape — see Errors.

Examples

hanzo studio runs create
import { Configuration, StudioApi } from 'hanzoai';

const api = new StudioApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postStudioRuns({ brand: "<brand>", flow: "<flow>" });
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import StudioApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = StudioApi(client).post_studio_runs(brand="<brand>", flow="<flow>")
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.StudioAPI.PostStudioRuns(context.Background()).Execute()
if err != nil {
	return err
}
use hanzo_client::apis::{configuration::Configuration, studio_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = studio_api::post_studio_runs(&cfg, Default::default()).await?;
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.StudioApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new StudioApi(client).postStudioRuns();
curl -X POST https://api.hanzo.ai/v1/studio/runs \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "brand": "<brand>",
       "flow": "<flow>"
     }'

MCP reaches studio through the studio tool, which names its 32 operations with its own verbs — this one among them, under a name only MCP declares. describe explains any of them:

curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "describe",
         "arguments": {
           "op": "list_studio_brands"
         }
       }
     }'

Studio API · All Hanzo APIs · Interactive reference

Was this page useful?
Broken link or missing step? Drop it in #docs on Discord or open a PR.