Create an App Run
POST /openapi/v1/app-runs
Authorization: Bearer <API_KEY>
Content-Type: application/json
Request parameters
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
appId | Body | string | Yes | App ID |
projectId | Body | string | Yes | Project ID; determines result ownership and the project charged |
publishTag | Body | string | No | Release Tag: production or test; mutually exclusive with publishVersion |
publishVersion | Body | integer | No | Exact immutable version, minimum 1; mutually exclusive with publishTag |
inputJson | Body | object | Yes | Map from the App's declared input keys to input values |
Use List published Apps to obtain an App ID in the project, then call Get App details before creating a Run. inputJson must follow the current data.inputs returned by App details.
Request body example
{
"appId": "REPLACE_WITH_YOUR_APP_ID",
"projectId": "REPLACE_WITH_YOUR_PROJECT_ID",
"publishTag": "production",
"inputJson": {
"outfit_prompt": "Fashion outfit flat lay on white background",
"character_image": {
"url": "https://example.com/a.png"
},
"duration": -1
}
}
Request body fields
Parameters with type: "prompt" are hidden from OpenAPI and cannot be supplied by callers. Runs use the Prompt default from the selected release. Submit only the inputs listed by App details; use "inputJson": {} when no public inputs need a value.
| Field | Type | Description |
|---|---|---|
appId | string | Required; App ID |
projectId | string | Required; Project ID that determines result ownership and the project charged |
publishTag | string | Optional; production or test, mutually exclusive with publishVersion |
publishVersion | integer | Optional; exact immutable version, minimum 1, mutually exclusive with publishTag |
inputJson | object | Required; map from the App's declared input keys to input values |
inputJson.outfit_prompt | string | Text input for the example App; actual fields must follow data.inputs returned by App details |
inputJson.character_image | object | Image input object for the example App |
inputJson.character_image.url | string | Absolute HTTPS media URL directly accessible to the execution service |
inputJson.duration | number | Example setting input; must exactly match a same-typed value in the selected release's options[].value |
With no selector, the API resolves production. Supplying both selectors, an invalid Tag, a version below 1, or any unknown top-level field returns INVALID_REQUEST. An unavailable Tag or version returns APP_NOT_FOUND.
inputJson rules
Each App's publisher defines its input keys, types, required status, and defaults. Clients may send only declared keys.
When an optional media input has required=false, omit its key to mean that no media is supplied for this Run.
The server does not fall back to a publishing example or original output. Do not send an explicit null;
null is not omission and returns APP_INPUT_INVALID.
Text input example
Media input example
Setting input example
{
"duration": -1,
"resolution": "1080P"
}
Submit a setting option's value, not the entire {value,label} object. For older releases with primitive options, submit the primitive directly.
Strings and numbers are distinct, so "-1" is invalid when the declared option is -1. Options are
frozen per published version; do not infer them from a newer model catalog.
A media object must contain exactly one url field. The media URL must:
- Be an absolute HTTPS URL;
- Contain no username, password, or URL fragment;
- Be accessible during the Run without browser sign-in, Cookies, or interaction;
- Not point to localhost, private networks, link-local networks, CGNAT, reserved ranges, or cloud metadata addresses;
- Be downloadable by the execution service within a reasonable time.
Direct binary uploads, Base64, data: URLs, HTTP URLs, other resource IDs, and additional media object fields such as a filename are not supported.
The API returns APP_INPUT_INVALID when:
- An undeclared key is supplied;
- A required input without a default is missing;
- A text input is not a string;
- A
settinginput is not in the selected release's frozenoptions[].value, or its primitive type differs; - Any input is explicitly set to
null; - A media input is not
{ "url": "https://..." }; - A URL cannot be parsed or violates the security rules.
Creation semantics and billing
When accepting the request, the server resolves the selector and records the exact publishVersion and the publishTag associated with that version at that moment. For an exact-version request, it records production or test when applicable, prefers production if both Tags point to the version, and records null when neither does. Taking down the App, publishing a new version, or switching a Tag later does not affect a Run that was already created successfully.
The success status is HTTP 201.
Success response example
200success on successproduction or test associated with the version when the Run was created; null when it had no TagestimatedPrice is used for the pre-Run balance check and display. It is not a final price or price cap. Both the balance check and actual charges belong to the project identified by projectId; actualPrice reflects the charges actually incurred. Every POST creates a new Run.
Selecting a model and dependent defaults
Submit a numeric ID for a model setting, for example {"model":22}. Omitting the model uses its published default; omitting dependent settings such as resolution or duration uses the selected model's frozen defaults. Explicit incompatible values, numeric strings, and settings disabled for that model return APP_INPUT_INVALID instead of being silently replaced. Use the input keys returned by App details. Resolved defaults are included in the run record and idempotency fingerprint.