# Create a run

POST https://fusara.ai/api/v3/run

Returns 202 with the run ID and expected cost, or 200 if already terminal. Successful idempotent replay returns the original Run without repricing. Outputs and errors are omitted until applicable. Supply a public HTTPS webhook_url directly; no registration or shared receiver secret is required. Webhooks contain the full Run JSON with ready output URLs: match the expected Run, save the result and acknowledge with 2xx. Signature verification is optional; do not make JWKS setup or a result GET a prerequisite for integration. Without verification, sender authenticity is unverified. Fusara always signs notifications with Ed25519; public keys: /.well-known/jwks.json. Billing may settle later, producing a second snapshot with a distinct webhook-id. Delivery is at least once, with up to 10 total attempts; snapshots can arrive out of order. Use webhook-id to deduplicate and never replace settled cost with pending cost.

## Example request

```bash
curl 'https://fusara.ai/api/v3/run' \
  -H "Authorization: Bearer $FUSARA_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "model": "qwen-image21-create",
  "prompt": "A white ceramic lamp on a pale lavender background, soft studio light."
}'
```

## Parameters

- `Idempotency-Key` (string): Optional. Reuse the same key and body to recover the same run. On 409 request_in_progress, wait for Retry-After and retry with that same key and unchanged body. A different body returns 422 idempotency_conflict. Scope: API-key owner. Keys remain bound even after rejection, for the lifetime of the submission. header; Pattern: ^[!-~]+$; Minimum length: 1; Maximum length: 256.

## Request body

Flat model-specific settings and named reference arrays. Discover exact supported fields, defaults and bounds in GET /api/v3/models/{model}: request_schema. Unknown fields are rejected; there are no input/parameters wrappers. Maximum body: 1 MiB.

- `model` (string, required): Exact public model ID from model discovery. Keep any variant suffix, including slashes.
- `prompt` (string): Text instruction. Availability and whether it is required depend on the selected model's request_schema. Estimates can omit it when the price is determined by settings alone.
- `webhook_url` (string): Optional public HTTPS callback URL; no registration required. Receives the full Run JSON, ready to save without another GET. Signature verification is optional; without it, sender authenticity is unverified. Format: uri; Maximum length: 2048.

## Responses

### 200

Run already terminal, including an idempotent replay.

#### Response headers

- `Location` (string, required): Absolute URL for reading this run. Authenticate GET requests with your API key. Format: uri.
- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `id` (integer, required): Numeric run ID. Use it for status, results, cancellation and matching webhooks. Format: int64; Minimum: 0; Maximum: 4294967295.
- `status` (string, required): queued or running while in progress; succeeded, failed or canceled when terminal.
- `cost` (object, required)
- `cost.unit` (string, required): Billing unit: common_fuz.
- `cost.expected` (string, required): Total accepted estimate for this run, as a decimal string.
- `cost.status` (string, required): pending until billing is confirmed, then settled. Generation can finish before settlement.
- `cost.charged` (string): Confirmed final charge, as a decimal string. Omitted while pending; confirmed zero is 0.0000.
- `outputs` (object[]): Applicable outputs in their original order. Omitted when none exist; a failed run can still have usable partial outputs.
- `outputs.type` (string, required) Alternative values: "text", "json", "boolean", "image", "video", "audio", "media", "model_asset".
- `outputs.media_id` (integer): Reusable account media ID when this output is a file. Format: int64; Minimum: 0; Maximum: 4294967295.
- `outputs.url` (string): Download URL when the file is available. Save it before url_expires_at.
- `outputs.url_expires_at` (string): UTC expiry of this output URL, when provided. Format: date-time.
- `outputs.expired` (boolean): True when the media is no longer available; its dead URL is omitted.
- `outputs.value` (any JSON value): Inline result: a string for type=text, a native JSON value for type=json, or a boolean for type=boolean. Empty strings, false and JSON null are valid values. Omitted for files and model assets. When type is "text": required; string; When type is "json": required; any JSON value; When type is "boolean": required; boolean; When type is "image" or "video" or "audio" or "media" or "model_asset": must be omitted.
- `outputs.model_asset_id` (integer) Format: int64; Minimum: 0; Maximum: 4294967295.
- `error` (object)
- `error.code` (string, required): Machine-readable generation failure code.
- `error.message` (string, required): Human-readable explanation of the generation failure.

### 202

Run accepted; queued or running.

#### Response headers

- `Location` (string, required): Absolute URL for reading this run. Authenticate GET requests with your API key. Format: uri.
- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

```json
{
  "id": 123456,
  "status": "queued",
  "cost": {
    "unit": "common_fuz",
    "expected": "40.0000",
    "status": "pending"
  }
}
```

#### Response body

- `id` (integer, required): Numeric run ID. Use it for status, results, cancellation and matching webhooks. Format: int64; Minimum: 0; Maximum: 4294967295.
- `status` (string, required): queued or running while in progress; succeeded, failed or canceled when terminal.
- `cost` (object, required)
- `cost.unit` (string, required): Billing unit: common_fuz.
- `cost.expected` (string, required): Total accepted estimate for this run, as a decimal string.
- `cost.status` (string, required): pending until billing is confirmed, then settled. Generation can finish before settlement.
- `cost.charged` (string): Confirmed final charge, as a decimal string. Omitted while pending; confirmed zero is 0.0000.
- `outputs` (object[]): Applicable outputs in their original order. Omitted when none exist; a failed run can still have usable partial outputs.
- `outputs.type` (string, required) Alternative values: "text", "json", "boolean", "image", "video", "audio", "media", "model_asset".
- `outputs.media_id` (integer): Reusable account media ID when this output is a file. Format: int64; Minimum: 0; Maximum: 4294967295.
- `outputs.url` (string): Download URL when the file is available. Save it before url_expires_at.
- `outputs.url_expires_at` (string): UTC expiry of this output URL, when provided. Format: date-time.
- `outputs.expired` (boolean): True when the media is no longer available; its dead URL is omitted.
- `outputs.value` (any JSON value): Inline result: a string for type=text, a native JSON value for type=json, or a boolean for type=boolean. Empty strings, false and JSON null are valid values. Omitted for files and model assets. When type is "text": required; string; When type is "json": required; any JSON value; When type is "boolean": required; boolean; When type is "image" or "video" or "audio" or "media" or "model_asset": must be omitted.
- `outputs.model_asset_id` (integer) Format: int64; Minimum: 0; Maximum: 4294967295.
- `error` (object)
- `error.code` (string, required): Machine-readable generation failure code.
- `error.message` (string, required): Human-readable explanation of the generation failure.

### 400

invalid_header: supply only one authentication header, Authorization: Bearer or X-API-Key. invalid_json or invalid_request: malformed request body. invalid_media_url, unsafe_media_url or remote_media_redirect_invalid: replace the invalid or restricted source URL. unsupported_media_link, unsupported_media_url, remote_media_folder_not_supported or remote_media_document_not_supported: use a direct link to a supported media file. invalid_idempotency_key: supply one key containing 1 to 256 visible ASCII characters, without whitespace.

#### Response headers

- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 401

authentication_required: the API key is missing or invalid. Public methods allow omission, but reject invalid supplied credentials.

#### Response headers

- `WWW-Authenticate` (string, required): Bearer authentication challenge. Values: "Bearer".
- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 402

insufficient_balance: add funds or reduce the requested cost before submitting.

#### Response headers

- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 403

permission_denied: the account cannot access this resource. remote_media_access_required, remote_media_download_disabled or remote_media_challenge_required: the source blocks automated download; use a publicly downloadable file.

#### Response headers

- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 404

remote_media_not_found: the source file is missing or its link has expired; replace the URL. resource_not_found: the selected model or a referenced media/model asset is missing or inaccessible.

#### Response headers

- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 409

request_in_progress (retryable: true): the original submission is still being accepted. Wait for Retry-After, then retry with the same Idempotency-Key and unchanged body; a new key could generate and charge twice.

#### Response headers

- `Retry-After` (integer): When supplied, the minimum number of seconds to wait before retrying a transient failure. Preserve the original idempotency key and body when retrying a submission. Minimum: 1.
- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 410

media_expired: a referenced input has expired. Replace it with available media or import the original file again. Repeating the expired reference cannot restore it. If using an idempotency key, a corrected body needs a new key; the original key remains bound even after rejection.

#### Response headers

- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 413

request_too_large: reduce the JSON body to at most 1 MiB. remote_media_too_large: use a smaller source file within the media upload limit.

#### Response headers

- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 415

unsupported_media_type: send the body as application/json.

#### Response headers

- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 422

validation_error: correct the fields identified by error.errors[].pointer; unknown fields and query parameters are rejected. idempotency_conflict (retryable: false): the key belongs to a different body. Restore the original body to recover that submission; use a new key only when intending to submit a different request. Do not retry automatically.

#### Response headers

- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 429

rate_limited (retryable: true): wait for the indicated delay, then retry. Use bounded backoff if no delay is supplied.

#### Response headers

- `Retry-After` (integer): When supplied, the minimum number of seconds to wait before retrying a transient failure. Preserve the original idempotency key and body when retrying a submission. Minimum: 1.
- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 500

internal_error: unexpected server failure. Do not assume a submission failed before acceptance; retrieve the run if known, or recover it with the original idempotency key and unchanged body. Without a key, an uncertain submission must not be retried automatically.

#### Response headers

- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 502

remote_media_provider_unavailable (retryable: true): the source could not be resolved, is temporarily unavailable or throttled the download. Retry after the indicated delay, or use bounded backoff when absent.

#### Response headers

- `Retry-After` (integer): When supplied, the minimum number of seconds to wait before retrying a transient failure. Preserve the original idempotency key and body when retrying a submission. Minimum: 1.
- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 503

remote_media_provider_not_configured (retryable: false): this source's import service is unavailable; use another supported source or contact support. execution_paused or webhook_unavailable (retryable: true): submission or webhook setup is temporarily unavailable. Wait for the indicated delay, then retry with the same key and unchanged body.

#### Response headers

- `Retry-After` (integer): When supplied, the minimum number of seconds to wait before retrying a transient failure. Preserve the original idempotency key and body when retrying a submission. Minimum: 1.
- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

### 504

remote_media_timeout (retryable: true): the source download timed out. Retry after the indicated delay, or use bounded backoff when absent.

#### Response headers

- `Retry-After` (integer): When supplied, the minimum number of seconds to wait before retrying a transient failure. Preserve the original idempotency key and body when retrying a submission. Minimum: 1.
- `X-Request-Id` (string, required): Support/trace identifier for this HTTP request.

#### Response body

- `error` (object, required)
- `error.code` (string, required): Machine-readable request error code.
- `error.message` (string, required): Human-readable explanation.
- `error.retryable` (boolean, required): Whether the failure is transient. For uncertain POST outcomes, preserve the original idempotency key and body.
- `error.errors` (object[]): Field errors when applicable. Omitted otherwise.
- `error.errors.pointer` (string, required): JSON Pointer to the invalid field, such as /images/0/url.
- `error.errors.code` (string, required): Machine-readable field error code.
- `error.errors.message` (string, required): How this field failed validation.

