<!-- /en/docs/creative-api (en) -->

# Images, text, music and speech

REST contracts for six Make modules; access and pricing depend on your account and the selected operation.

## Connection and request execution

Paths below include `/franklab/api`. Authenticate with your account key in `X-API-Key`; keep it in a server environment variable. Single-request template:

```bash
export FRANKLAB_BASE_URL='https://apergrex.ru/franklab/api'
# FRANKLAB_KEY is already set through your secure environment
cat > request.json <<'JSON'
{"model_key":"moon_gpt","prompt":"Return the word OK.","max_output_tokens":16,"async_mode":true}
JSON
curl --fail-with-body --max-time 300 -X POST \
  -H "X-API-Key: ${FRANKLAB_KEY:?Set your account key}" \
  -H 'Content-Type: application/json' \
  --data-binary @request.json \
  "$FRANKLAB_BASE_URL/make/dola/generate"
```

The example generates content and may reserve funds. For another operation replace the route suffix, method and JSON using its table. `REPLACE_WITH_…` and `example.com` are templates to replace with your own IDs/media; do not run all examples in sequence. GET takes the stated query parameters and substituted path IDs, with no body.

Required fields and choices apply to the selected operation; conditions are shown separately. “Make default” is a form value that REST clients must explicitly send to reproduce Make behavior; it is not a promise of a server default.

## Billing, errors and retries

Check your [balance and tariff](/en/docs/billing) first. Alibaba provides `/make/alibaba/estimate`; generic `/v1/billing/pricing/estimate` takes a `modelId` from current `/v1/billing/pricing/catalog` and supported quote parameters. Catalog pricing IDs are not automatically `model_key`/`model_name`. Other operations may lack a standalone public quote; unknown cost is not zero. Reconcile the task reservation, final charge and refund with transactions. Frank (₣) is an internal accounting unit.

Errors: 400 invalid fields/model/media, 401 key failure, 403 access denied, 404 missing or inaccessible owned resource, 429 rate limit. Unavailable models, insufficient balance and execution errors can also appear in `code`, `message`/`msg`, `data.error`/`error_message` even with HTTP 200. Check HTTP and body. If POST outcome is unknown, retain identifiers and reconcile history/support before retrying; never blindly repeat paid submission. State, error and result shapes are module-specific.

## FrankLab Alibaba Image

If an estimate is unavailable for your account, confirm model access with [support](/en/docs/contacts) before submitting a generation.

Generate a Z-Image image or generate/edit with Qwen Image 3.0 and Qwen Image 3.0 Pro. These are synchronous REST operations: inspect the response before trying to poll. Check that your account has access to the selected model for estimation and generation.

For Qwen editing, set `operation:"image_edit"` and pass `editImageUrls`: 1–3 direct public HTTPS image URLs, PNG/JPEG/WebP, at most 10 MiB per image. The server imports the images for your account. Alternatively, upload each image with multipart `file` to `POST /franklab/api/franklab/jobs/upload` and collect each response's `data.storedFileId` into `editImageIds`. Send exactly one of `editImageUrls` or `editImageIds`; IDs must belong to your account. Qwen `width`/`height` must be supplied, each at most 2048, with total area between 512² and 2048² pixels; `n` is 1–6 (default 1). `prompt_extend_mode=agent` only works for text-to-image. Qwen output is PNG. Z-Image `size` uses `*`, such as `1024*1024`.

On success inspect `data.imageUrl` (first image), `data.taskId`, dimensions and `estimated_cost_franks`/`final_cost_franks`/`cost_status`. HTTP success alone is insufficient: also inspect `code` and `error_message`. Estimates are customer quotes and do not create images. Qwen estimates use `qwenOperation`; generation uses `operation`. `/make/alibaba/status/:taskId` polls video and must not be used for these image results.

| Operation | Method | Path |
|---|---|---|
| `z-image-turbo:text_to_image` | POST | `/franklab/api/make/alibaba/images` |
| `qwen-image-3.0-pro:text_to_image` | POST | `/franklab/api/make/alibaba/images` |
| `qwen-image-3.0-pro:image_edit` | POST | `/franklab/api/make/alibaba/images` |
| `qwen-image-3.0:text_to_image` | POST | `/franklab/api/make/alibaba/images` |
| `qwen-image-3.0:image_edit` | POST | `/franklab/api/make/alibaba/images` |
| `estimate` | POST | `/franklab/api/make/alibaba/estimate` |

### z-image-turbo:text_to_image

`POST /franklab/api/make/alibaba/images`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model` | string | yes | `"z-image-turbo"` |
| `prompt` | string | yes | — |
| `size` | string | yes | `["1024*1024","832*1248","1248*832","864*1152","1152*864","896*1152","1152*896","720*1280","576*1344","1280*720","1344*576","1280*1280","1024*1536","1536*1024","1104*1472","1472*1104","1120*1440","1440*1120","864*1536","720*1680","1536*864","1680*720","1536*1536","1248*1872","1872*1248","1296*1728","1728*1296","1344*1728","1728*1344","1152*2048","864*2016","2048*1152","2016*864"]`; Make default: "1024*1024" |
| `seed` | integer | no | — |

JSON template:

```json
{
  "model": "z-image-turbo",
  "prompt": "A short calm synthetic test.",
  "size": "1024*1024"
}
```

### qwen-image-3.0-pro:text_to_image

`POST /franklab/api/make/alibaba/images`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model` | string | yes | `"qwen-image-3.0-pro"` |
| `operation` | string | yes | `"text_to_image"` |
| `prompt` | string | yes | — |
| `width` | integer | yes | Make default: 1024 |
| `height` | integer | yes | Make default: 1024 |
| `n` | integer | no | Server default: 1 |
| `seed` | integer | no | — |
| `negative_prompt` | string | no | — |
| `prompt_extend` | boolean | no | Make default: false |
| `prompt_extend_mode` | string | no | `["direct","agent"]`; Make default: "direct" |
| `enable_thinking` | boolean | no | Make default: false |
| `watermark` | boolean | no | Make default: false |

JSON template:

```json
{
  "model": "qwen-image-3.0-pro",
  "operation": "text_to_image",
  "prompt": "A short calm synthetic test.",
  "width": 1024,
  "height": 1024
}
```

### qwen-image-3.0-pro:image_edit

`POST /franklab/api/make/alibaba/images`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model` | string | yes | `"qwen-image-3.0-pro"` |
| `operation` | string | yes | `"image_edit"` |
| `prompt` | string | yes | — |
| `width` | integer | yes | Make default: 1024 |
| `height` | integer | yes | Make default: 1024 |
| `n` | integer | no | Server default: 1 |
| `editImageUrls` | string[] | conditional | 1–3 direct HTTPS URLs; PNG/JPEG/WebP, ≤10 MiB each; omit editImageIds. |
| `editImageIds` | string[] | conditional | 1–3 owned UUIDs from upload data.storedFileId; omit editImageUrls. |
| `seed` | integer | no | — |
| `negative_prompt` | string | no | — |
| `prompt_extend` | boolean | no | Make default: false |
| `enable_thinking` | boolean | no | Make default: false |
| `watermark` | boolean | no | Make default: false |

JSON template:

```json
{
  "model": "qwen-image-3.0-pro",
  "operation": "image_edit",
  "prompt": "Replace the background with a pale blue studio backdrop.",
  "width": 1024,
  "height": 1024,
  "editImageUrls": [
    "https://media.example.com/product-front.png"
  ]
}
```

### qwen-image-3.0:text_to_image

`POST /franklab/api/make/alibaba/images`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model` | string | yes | `"qwen-image-3.0"` |
| `operation` | string | yes | `"text_to_image"` |
| `prompt` | string | yes | — |
| `width` | integer | yes | Make default: 1024 |
| `height` | integer | yes | Make default: 1024 |
| `n` | integer | no | Server default: 1 |
| `seed` | integer | no | — |
| `negative_prompt` | string | no | — |
| `prompt_extend` | boolean | no | Make default: false |
| `prompt_extend_mode` | string | no | `["direct","agent"]`; Make default: "direct" |
| `enable_thinking` | boolean | no | Make default: false |
| `watermark` | boolean | no | Make default: false |

JSON template:

```json
{
  "model": "qwen-image-3.0",
  "operation": "text_to_image",
  "prompt": "A short calm synthetic test.",
  "width": 1024,
  "height": 1024
}
```

### qwen-image-3.0:image_edit

`POST /franklab/api/make/alibaba/images`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model` | string | yes | `"qwen-image-3.0"` |
| `operation` | string | yes | `"image_edit"` |
| `prompt` | string | yes | — |
| `width` | integer | yes | Make default: 1024 |
| `height` | integer | yes | Make default: 1024 |
| `n` | integer | no | Server default: 1 |
| `editImageUrls` | string[] | conditional | 1–3 direct HTTPS URLs; PNG/JPEG/WebP, ≤10 MiB each; omit editImageIds. |
| `editImageIds` | string[] | conditional | 1–3 owned UUIDs from upload data.storedFileId; omit editImageUrls. |
| `seed` | integer | no | — |
| `negative_prompt` | string | no | — |
| `prompt_extend` | boolean | no | Make default: false |
| `enable_thinking` | boolean | no | Make default: false |
| `watermark` | boolean | no | Make default: false |

JSON template:

```json
{
  "model": "qwen-image-3.0",
  "operation": "image_edit",
  "prompt": "Replace the background with a pale blue studio backdrop.",
  "width": 1024,
  "height": 1024,
  "editImageUrls": [
    "https://media.example.com/product-front.png"
  ]
}
```

### estimate

For an image-edit estimate, send `qwenOperation:"image_edit"`, `imageCount`, `width`, `height` and `n` with the selected model. Estimates do not download reference URLs.

For image quotes use `model=z-image-turbo|qwen-image-3.0-pro|qwen-image-3.0`. Omit model for HappyHorse video quotes; use `wan3.0-video` for WAN. `happyhorse-1.1` is a Make selector, not an accepted REST DTO value.

`POST /franklab/api/make/alibaba/estimate`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `media` | string | yes | — |
| `model` | string | no | — |
| `operation` | string | no | — |
| `width` | integer | no | — |
| `height` | integer | no | — |
| `n` | integer | no | — |
| `imageCount` | integer | no | — |
| `resolution` | string | no | — |
| `durationSeconds` | integer | no | — |
| `qwenOperation` | string | no | `text_to_image` / `image_edit`; Qwen quote only |

JSON template:

```json
{
  "media": "image",
  "model": "z-image-turbo"
}
```

## JUPITER

Choose a route and model before submission. The Make `mode` selects the route and is **not sent in the REST body**. MIST uses `model_name=mist`, Kling uses `jupiter-v1-5`; Gemini/Seedream use `model_id`; subscription routes use `execution_mode`. Each route can have independent availability. A model list does not guarantee generation access.

Reference shapes differ: MIST/Kling/Gemini use `image_list:[{"image_url":"https://…"}]`; Seedream uses `image:["https://…"]`; subscription routes use `reference_images:["https://…"]`; legacy Nano Banana Pro uses `image_input:["https://…"]`; Grok editing uses `image:{"url":"https://…"}`. Direct public HTTPS URLs are supported; uploading first is optional. For Kling (`model_name:"jupiter-v1-5"`), reference each `image_list` entry in `prompt` as `<<<image_1>>>`, `<<<image_2>>>`, and so on, in array order. MIST does not require these tokens.

Save both the submit route and `data.task_id`/`data.taskId`. Most status routes append `/:taskId`; legacy Nano Banana Pro instead uses `/v1/google/:taskId/record-info`. Do not send a Gemini or Seedream task to the omni-image poller. Poll about every 5 seconds with a bounded deadline. Inspect `data.status`, `task_status` or `state`; successful aliases include `completed`, `succeed`, `success`, `succeeded`, `done`. Failed/refunded/cancelled states stop polling. A wait timeout does not authorize resubmission.

Images may be in `data.images`, `data.task_result.images`, `data.result.task_result.images`, `data.output.images` or `data.output.imageUrls`; older responses can contain JSON-encoded `data.resultJson.resultUrls`. Gemini can also return `output_text`, `grounding`, `citations`, `search_suggestions` and `interaction_id`. Read actual REST fields; Make's flattened `image_url` is a convenience projection. `final_cost_franks` accompanied by `cost_status=reserved` is still a reservation.

| Operation | Method | Path |
|---|---|---|
| `mist` | POST | `/franklab/api/v1/images/omni-image` |
| `gpt_image_codex` | POST | `/franklab/api/v1/images/gpt-image-codex` |
| `google_sub_image` | POST | `/franklab/api/v1/images/google-sub` |
| `jupiter` | POST | `/franklab/api/v1/images/omni-image` |
| `xai_imagine_image_2` | POST | `/franklab/api/v1/images/xai-imagine` |
| `xai_imagine_image` | POST | `/franklab/api/v1/images/xai-imagine` |
| `google_gemini_image` | POST | `/franklab/api/v1/google/gemini-image` |
| `seedream_image` | POST | `/franklab/api/v1/images/seedream-image` |
| `google_nano_banana_pro` | POST | `/franklab/api/v1/google/nano-banana-pro` |
| `poll:v1/google/:taskId/record-info` | GET | `/franklab/api/v1/google/:taskId/record-info` |
| `poll:v1/google/gemini-image/:taskId` | GET | `/franklab/api/v1/google/gemini-image/:taskId` |
| `poll:v1/images/google-sub/:taskId` | GET | `/franklab/api/v1/images/google-sub/:taskId` |
| `poll:v1/images/gpt-image-codex/:taskId` | GET | `/franklab/api/v1/images/gpt-image-codex/:taskId` |
| `poll:v1/images/omni-image/:taskId` | GET | `/franklab/api/v1/images/omni-image/:taskId` |
| `poll:v1/images/seedream-image/:taskId` | GET | `/franklab/api/v1/images/seedream-image/:taskId` |
| `poll:v1/images/xai-imagine/:taskId` | GET | `/franklab/api/v1/images/xai-imagine/:taskId` |

### mist

`POST /franklab/api/v1/images/omni-image`

Poll: `GET /franklab/api/v1/images/omni-image/:taskId`.

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model_name` | string | yes | `"mist"` |
| `quality` | string | no | `["auto","low","medium","high"]`; Make default: "auto" |
| `output_format` | string | no | `["png","jpeg","webp"]`; Make default: "png" |
| `background` | string | no | `["auto","opaque"]`; Make default: "auto" |
| `moderation` | string | no | `["auto","low"]`; Make default: "auto" |
| `partial_images` | string | no | `[0,1,2,3]`; Make default: 0 |
| `input_fidelity` | string | no | `["high","auto"]`; Make default: "high" |
| `prompt` | string | yes | — |
| `image_list` | array | no | `image_url:string` |
| `aspect_ratio` | string | no | `["1:1","16:9","9:16","21:9","custom"]`; Make default: "1:1" |
| `custom_aspect_ratio` | string | no | When aspect_ratio=custom |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "model_name": "mist",
  "prompt": "Place this product on a wooden table.",
  "image_list": [{"image_url": "https://media.example.com/product-front.png"}]
}
```

### gpt_image_codex

`POST /franklab/api/v1/images/gpt-image-codex`

Poll: `GET /franklab/api/v1/images/gpt-image-codex/:taskId`.

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `execution_mode` | string | yes | `"openai_codex"` |
| `quality` | string | no | `["low","medium","high"]`; Make default: "medium" |
| `prompt` | string | yes | — |
| `reference_images` | array | no | items: string |
| `aspect_ratio` | string | no | `["1:1","16:9","9:16","custom"]`; Make default: "1:1" |
| `custom_aspect_ratio` | string | no | When aspect_ratio=custom |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "execution_mode": "openai_codex",
  "prompt": "A short calm synthetic test."
}
```

### google_sub_image

`POST /franklab/api/v1/images/google-sub`

Poll: `GET /franklab/api/v1/images/google-sub/:taskId`.

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `execution_mode` | string | yes | `"google_subscription"` |
| `prompt` | string | yes | — |
| `reference_images` | array | no | items: string |
| `aspect_ratio` | string | no | `["1:1","16:9","9:16","4:3","3:4"]`; Make default: "1:1" |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "execution_mode": "google_subscription",
  "prompt": "A short calm synthetic test."
}
```

### jupiter

`POST /franklab/api/v1/images/omni-image`

Poll: `GET /franklab/api/v1/images/omni-image/:taskId`.

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model_name` | string | yes | `"jupiter-v1-5"` |
| `resolution` | string | yes | `["1k","2k","4k"]`; Make default: "1k" |
| `result_type` | string | no | `["single","series"]`; Make default: "single" |
| `series_amount` | integer or string | no | `["auto",2,3,4,5,6,7,8,9]`; Make default: "auto"; When result_type=series |
| `prompt` | string | yes | — |
| `n` | number | no | Make default: 1 |
| `image_list` | array | no | `image_url:string` |
| `element_list` | array | no | `element_id:string` |
| `aspect_ratio` | string | no | `["auto","1:1","16:9","9:16","4:3","3:4","3:2","2:3","21:9","custom"]`; Make default: "auto" |
| `custom_aspect_ratio` | string | no | When aspect_ratio=custom |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "model_name": "jupiter-v1-5",
  "resolution": "1k",
  "prompt": "Place the product from <<<image_1>>> on a wooden table.",
  "image_list": [{"image_url": "https://media.example.com/product-front.png"}]
}
```

### xai_imagine_image_2

`POST /franklab/api/v1/images/xai-imagine`

Poll: `GET /franklab/api/v1/images/xai-imagine/:taskId`.

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model_name` | string | yes | `"xai-imagine-image-2"` |
| `response_format` | string | yes | `"url"` |
| `prompt` | string | yes | — |
| `quality` | string | yes | `["medium","low"]`; Make default: "medium" |
| `aspect_ratio` | string | yes | `["auto","1:1","16:9","9:16","4:3","3:4","3:2","2:3","2:1","1:2","19.5:9","9:19.5","20:9","9:20"]`; Make default: "auto" |
| `resolution` | string | yes | `["1k","2k"]`; Make default: "1k" |
| `n` | number | yes | Make default: 1 |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "model_name": "xai-imagine-image-2",
  "response_format": "url",
  "prompt": "A short calm synthetic test.",
  "quality": "medium",
  "aspect_ratio": "auto",
  "resolution": "1k",
  "n": 1
}
```

### xai_imagine_image

`POST /franklab/api/v1/images/xai-imagine`

Poll: `GET /franklab/api/v1/images/xai-imagine/:taskId`.

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model_name` | string | yes | `"xai-imagine-image-quality"` |
| `response_format` | string | yes | `"url"` |
| `execution_mode` | string | no | `["xai_api","supergrok"]`; Make default: "xai_api" |
| `prompt` | string | yes | — |
| `image` | object | no | When image edit requested; `url:string` |
| `aspect_ratio` | string | no | `["auto","1:1","16:9","9:16","4:3","3:4"]`; Make default: "auto" |
| `resolution` | string | no | `["1k","2k"]`; Make default: "1k" |
| `n` | number | no | Make default: 1 |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "model_name": "xai-imagine-image-quality",
  "response_format": "url",
  "prompt": "A short calm synthetic test."
}
```

### google_gemini_image

`POST /franklab/api/v1/google/gemini-image`

Poll: `GET /franklab/api/v1/google/gemini-image/:taskId`.

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model_id` | string | yes | `["gemini-3.1-flash-image","gemini-3.1-flash-lite-image","gemini-3-pro-image","gemini-2.5-flash-image"]`; Make default: "gemini-3.1-flash-image" |
| `prompt` | string | conditional | When model_id=gemini-3.1-flash-image |
| `image_list` | array | no | When model_id=gemini-3.1-flash-image; `image_url:string` |
| `video_url` | string | no | When model_id=gemini-3.1-flash-image |
| `previous_interaction_id` | string | no | When model_id=gemini-3.1-flash-image |
| `aspect_ratio` | string | no | `["auto","1:1","16:9","9:16","4:3","3:4","3:2","2:3","4:5","5:4","1:4","1:8","4:1","8:1","21:9"]`; Make default: "auto"; When model_id=gemini-3.1-flash-image |
| `image_size` | string | no | `["0.5K","1K","2K","4K"]`; Make default: "1K"; When model_id=gemini-3.1-flash-image |
| `output_format` | string | no | `["png","jpeg","webp"]`; Make default: "png"; When model_id=gemini-3.1-flash-image |
| `use_google_search` | boolean | no | Make default: false; When model_id=gemini-3.1-flash-image |
| `use_image_search` | boolean | no | Make default: false; When model_id=gemini-3.1-flash-image |
| `prompt` | string | conditional | When model_id=gemini-3.1-flash-lite-image |
| `image_list` | array | no | When model_id=gemini-3.1-flash-lite-image; `image_url:string` |
| `aspect_ratio` | string | no | `["auto","1:1","16:9","9:16","4:3","3:4","3:2","2:3","4:5","5:4","21:9"]`; Make default: "auto"; When model_id=gemini-3.1-flash-lite-image |
| `output_format` | string | no | `["png","jpeg","webp"]`; Make default: "png"; When model_id=gemini-3.1-flash-lite-image |
| `prompt` | string | conditional | When model_id=gemini-3-pro-image |
| `image_list` | array | no | When model_id=gemini-3-pro-image; `image_url:string` |
| `previous_interaction_id` | string | no | When model_id=gemini-3-pro-image |
| `aspect_ratio` | string | no | `["auto","1:1","16:9","9:16","4:3","3:4","3:2","2:3","4:5","5:4","21:9"]`; Make default: "auto"; When model_id=gemini-3-pro-image |
| `image_size` | string | no | `["1K","2K","4K"]`; Make default: "1K"; When model_id=gemini-3-pro-image |
| `output_format` | string | no | `["png","jpeg","webp"]`; Make default: "png"; When model_id=gemini-3-pro-image |
| `use_google_search` | boolean | no | Make default: false; When model_id=gemini-3-pro-image |
| `prompt` | string | conditional | When model_id=gemini-2.5-flash-image |
| `image_list` | array | no | When model_id=gemini-2.5-flash-image; `image_url:string` |
| `aspect_ratio` | string | no | `["auto","1:1","16:9","9:16","4:3","3:4","3:2","2:3","4:5","5:4","21:9"]`; Make default: "auto"; When model_id=gemini-2.5-flash-image |
| `output_format` | string | no | `["png","jpeg","webp"]`; Make default: "png"; When model_id=gemini-2.5-flash-image |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "model_id": "gemini-3.1-flash-image",
  "prompt": "A flat blue circle on white.",
  "image_size": "0.5K"
}
```

### seedream_image

`POST /franklab/api/v1/images/seedream-image`

Poll: `GET /franklab/api/v1/images/seedream-image/:taskId`.

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model_id` | string | yes | `["seedream-5-0-lite","seedream-5-0-pro"]`; Make default: "seedream-5-0-lite" |
| `prompt` | string | conditional | When model_id=seedream-5-0-lite |
| `image` | array | no | When model_id=seedream-5-0-lite; items: string |
| `sequential_image_generation` | string | no | `["disabled","auto"]`; Make default: "disabled"; When model_id=seedream-5-0-lite |
| `max_images` | string | no | `[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]`; Make default: 4; When model_id=seedream-5-0-lite; sequential_image_generation=auto |
| `resolution` | string | conditional | `["2K","3K","4K"]`; Make default: "2K"; When model_id=seedream-5-0-lite |
| `aspect_ratio` | string | no | `["","1:1","4:3","3:4","16:9","9:16","3:2","2:3","21:9"]`; Make default: ""; When model_id=seedream-5-0-lite |
| `output_format` | string | no | `["jpeg","png"]`; Make default: "jpeg"; When model_id=seedream-5-0-lite |
| `watermark` | boolean | no | Make default: false; When model_id=seedream-5-0-lite |
| `prompt` | string | conditional | When model_id=seedream-5-0-pro |
| `image` | array | no | When model_id=seedream-5-0-pro; items: string |
| `resolution` | string | conditional | `["1K","2K"]`; Make default: "2K"; When model_id=seedream-5-0-pro |
| `aspect_ratio` | string | no | `["","1:1","4:3","3:4","16:9","9:16","3:2","2:3","21:9"]`; Make default: ""; When model_id=seedream-5-0-pro |
| `output_format` | string | no | `["jpeg","png"]`; Make default: "jpeg"; When model_id=seedream-5-0-pro |
| `watermark` | boolean | no | Make default: false; When model_id=seedream-5-0-pro |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "model_id": "seedream-5-0-lite",
  "prompt": "A flat blue circle on white.",
  "resolution": "2K"
}
```

### google_nano_banana_pro

`POST /franklab/api/v1/google/nano-banana-pro`

Poll: `GET /franklab/api/v1/google/:taskId/record-info`.

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `image_input` | array | no | items: string |
| `prompt` | string | no | — |
| `aspect_ratio` | string | no | `["1:1","9:16","16:9","3:4","4:3"]` |
| `resolution` | string | yes | `["1K","2K","4K"]`; Make default: "1K" |
| `output_format` | string | no | `["png","jpg"]`; Make default: "png" |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "resolution": "1K",
  "prompt": "A blue circle on white."
}
```

### poll:v1/google/:taskId/record-info

`GET /franklab/api/v1/google/:taskId/record-info`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | path |

### poll:v1/google/gemini-image/:taskId

`GET /franklab/api/v1/google/gemini-image/:taskId`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | path |

### poll:v1/images/google-sub/:taskId

`GET /franklab/api/v1/images/google-sub/:taskId`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | path |

### poll:v1/images/gpt-image-codex/:taskId

`GET /franklab/api/v1/images/gpt-image-codex/:taskId`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | path |

### poll:v1/images/omni-image/:taskId

`GET /franklab/api/v1/images/omni-image/:taskId`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | path |

### poll:v1/images/seedream-image/:taskId

`GET /franklab/api/v1/images/seedream-image/:taskId`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | path |

### poll:v1/images/xai-imagine/:taskId

`GET /franklab/api/v1/images/xai-imagine/:taskId`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | path |

## KUSOK v.2

All 16 actions use `POST /make/kusok/operation` with explicit `backend` and `action`. `backend=kusok` manages reusable elements and voices; `backend=moon` manages verification and Moon assets. Legacy service keys are refused for KUSOK operations. IDs are partner-scoped; a task ID, element ID, asset ID and voice ID are different values.

Create requires `element_name` (1–20 characters), `element_description` (up to 100) and `reference_type`. For `image_refer`, provide your `frontal_image` and optional `refer_images:[{"image_url":"…","type":"side"}]`; for `video_refer`, provide `refer_videos:[{"video_url":"…"}]`. Voice creation requires your authorized audio/video source. Use synthetic assets for integration tests, never another person's likeness or voice without permission.

Follow `data.should_poll` and `data.taskId`/`task_id`: create/recognize can return an async task, while list/get/delete/voice/verification operations have their own inline results. Poll `/make/kusok/async/tasks/:taskId` until `completed` or `failed`, then inspect `data.result` and `error_message`; a completed task still requires a usable `element_id` or recognition result. `poll_task` dispatch only requests polling and is not proof that the task is queued.

Moon `verify_start` returns a human H5 verification flow. Pass its verification token as REST **`byted_token`**, not the Make field `verification_token`. `verify_get_result` models HTTP `200` resolved, `202` pending, `409` failure and `410` expiry. Keep H5 links and tokens private. Use the returned verified `group_id` when creating assets; wait for asset status `Active` before generation references. Deletion changes resources; it is not a connection test.

| Operation | Method | Path |
|---|---|---|
| `kusok:create` | POST | `/franklab/api/make/kusok/operation` |
| `kusok:get` | POST | `/franklab/api/make/kusok/operation` |
| `kusok:list` | POST | `/franklab/api/make/kusok/operation` |
| `kusok:delete` | POST | `/franklab/api/make/kusok/operation` |
| `kusok:recognize` | POST | `/franklab/api/make/kusok/operation` |
| `kusok:poll_task` | POST | `/franklab/api/make/kusok/operation` |
| `kusok:create_voice` | POST | `/franklab/api/make/kusok/operation` |
| `kusok:get_voice` | POST | `/franklab/api/make/kusok/operation` |
| `kusok:list_voices` | POST | `/franklab/api/make/kusok/operation` |
| `kusok:list_preset_voices` | POST | `/franklab/api/make/kusok/operation` |
| `kusok:delete_voice` | POST | `/franklab/api/make/kusok/operation` |
| `moon:verify_start` | POST | `/franklab/api/make/kusok/operation` |
| `moon:verify_get_result` | POST | `/franklab/api/make/kusok/operation` |
| `moon:create_asset` | POST | `/franklab/api/make/kusok/operation` |
| `moon:get_asset` | POST | `/franklab/api/make/kusok/operation` |
| `moon:list_assets` | POST | `/franklab/api/make/kusok/operation` |
| `poll` | GET | `/franklab/api/make/kusok/async/tasks/:taskId` |
| `getAllKusoks RPC` | GET | `/franklab/api/make/kusok/elements` |

### kusok:create

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"create"` |
| `element_name` | string | yes | — |
| `element_description` | string | yes | — |
| `reference_type` | string | yes | `["image_refer","video_refer"]`; Make default: "image_refer" |
| `frontal_image` | string | no | — |
| `refer_images` | array | no | `image_url:string, type:string` |
| `refer_videos` | array | no | `video_url:string` |
| `element_voice_id` | string | no | — |
| `tag_list` | array | no | `tag_id:string` |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "backend": "kusok",
  "action": "create",
  "element_name": "Synthetic circle",
  "element_description": "A blue synthetic circle.",
  "reference_type": "image_refer",
  "frontal_image": "https://example.com/owned-synthetic-image.png"
}
```

### kusok:get

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"get"` |
| `element_id` | string | yes | — |

JSON template:

```json
{
  "backend": "kusok",
  "action": "get",
  "element_id": "REPLACE_WITH_OWNED_ELEMENT_ID"
}
```

### kusok:list

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"list"` |
| `pageNum` | integer | no | Make default: 1 |
| `pageSize` | integer | no | Make default: 200 |

JSON template:

```json
{
  "backend": "kusok",
  "action": "list"
}
```

### kusok:delete

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"delete"` |
| `element_id` | string | yes | — |

JSON template:

```json
{
  "backend": "kusok",
  "action": "delete",
  "element_id": "REPLACE_WITH_OWNED_ELEMENT_ID"
}
```

### kusok:recognize

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"recognize"` |
| `image` | string | yes | — |

JSON template:

```json
{
  "backend": "kusok",
  "action": "recognize",
  "image": "https://example.com/owned-synthetic-media.png"
}
```

### kusok:poll_task

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"poll_task"` |
| `task_id` | string | yes | — |

JSON template:

```json
{
  "backend": "kusok",
  "action": "poll_task",
  "task_id": "REPLACE_WITH_OWNED_TASK_ID"
}
```

### kusok:create_voice

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"create_voice"` |
| `voice_name` | string | yes | — |
| `voice_audio_list` | array | no | `audio_url:string` |
| `voice_url` | string | no | — |
| `video_id` | string | no | — |
| `source_task_id` | string | no | — |
| `callback_url` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "backend": "kusok",
  "action": "create_voice",
  "voice_name": "Synthetic Voice",
  "voice_url": "https://example.com/owned-synthetic-audio.mp3"
}
```

### kusok:get_voice

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"get_voice"` |
| `voice_id` | string | yes | — |

JSON template:

```json
{
  "backend": "kusok",
  "action": "get_voice",
  "voice_id": "REPLACE_WITH_OWNED_VOICE_ID"
}
```

### kusok:list_voices

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"list_voices"` |
| `pageNum` | integer | no | Make default: 1 |
| `pageSize` | integer | no | Make default: 200 |

JSON template:

```json
{
  "backend": "kusok",
  "action": "list_voices"
}
```

### kusok:list_preset_voices

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"list_preset_voices"` |
| `pageNum` | integer | no | Make default: 1 |
| `pageSize` | integer | no | Make default: 200 |

JSON template:

```json
{
  "backend": "kusok",
  "action": "list_preset_voices"
}
```

### kusok:delete_voice

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"kusok"` |
| `action` | string | yes | `"delete_voice"` |
| `voice_id` | string | yes | — |

JSON template:

```json
{
  "backend": "kusok",
  "action": "delete_voice",
  "voice_id": "REPLACE_WITH_OWNED_VOICE_ID"
}
```

### moon:verify_start

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"moon"` |
| `action` | string | yes | `"verify_start"` |
| `callback_url` | string | no | — |
| `project_name` | string | no | — |
| `external_task_id` | string | no | — |

JSON template:

```json
{
  "backend": "moon",
  "action": "verify_start"
}
```

### moon:verify_get_result

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"moon"` |
| `action` | string | yes | `"verify_get_result"` |
| `byted_token` | string | yes | — |
| `project_name` | string | no | — |

JSON template:

```json
{
  "backend": "moon",
  "action": "verify_get_result",
  "byted_token": "REPLACE_WITH_OWNED_BYTED_TOKEN"
}
```

### moon:create_asset

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"moon"` |
| `action` | string | yes | `"create_asset"` |
| `group_id` | string | yes | — |
| `url` | string | yes | — |
| `asset_type` | string | yes | `["Image","Video","Audio"]`; Make default: "Image" |
| `name` | string | no | — |
| `project_name` | string | no | — |

JSON template:

```json
{
  "backend": "moon",
  "action": "create_asset",
  "group_id": "REPLACE_WITH_OWNED_GROUP_ID",
  "url": "https://example.com/owned-synthetic-media.png",
  "asset_type": "Image"
}
```

### moon:get_asset

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"moon"` |
| `action` | string | yes | `"get_asset"` |
| `asset_id` | string | yes | — |
| `project_name` | string | no | — |

JSON template:

```json
{
  "backend": "moon",
  "action": "get_asset",
  "asset_id": "REPLACE_WITH_OWNED_ASSET_ID"
}
```

### moon:list_assets

`POST /franklab/api/make/kusok/operation`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `backend` | string | yes | `"moon"` |
| `action` | string | yes | `"list_assets"` |
| `group_id` | string | no | — |
| `statuses` | string | no | `["Active","Processing","Failed"]` |
| `name` | string | no | — |
| `pageNumber` | integer | no | Make default: 1 |
| `pageSize` | integer | no | Make default: 20 |

JSON template:

```json
{
  "backend": "moon",
  "action": "list_assets"
}
```

### poll

`GET /franklab/api/make/kusok/async/tasks/:taskId`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | path |

### getAllKusoks RPC

`GET /franklab/api/make/kusok/elements`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `pageNum` | integer | no | Server default: 1; query |
| `pageSize` | integer | no | Server default: 200; query |

## MOON GPT

Generate text, structured JSON and multimodal answers through `/make/dola`. Use a partner API key; legacy service keys return 403. Discover usable `model_key` values and capabilities with `GET /make/dola/models`. Omission selects `moon_gpt`; the choices below describe request values; use the model catalog for account access.

`prompt` is required. REST `async_mode` defaults to synchronous when omitted; send `true` to receive a durable `billing_task_id` and poll `/make/dola/tasks/:billing_task_id`. Poll while `data.cost_status=pending`. Read `output_text`/`content`, `parsed_json`, `json_parse_ok`/`json_parse_error`, `usage`, `conversation_id` and billing fields. A terminal billing record alone does not validate the returned JSON against your schema.

For `response_format=json_schema`, supply `json_schema_name` and an actual JSON object in `json_schema`. `max_output_tokens` is the REST name emitted by Make's `max_tokens` field; the API also accepts `max_tokens`. Limits are model-specific, at most 65536. Avoid sending both aliases. `thinking_level` and `thinking_budget` are mutually exclusive. Newer Gemini keys reject `temperature` and the old budget input. Conversation continuation must keep the same model and an owned `conversation_id` or supported `previous_response_id`.

Upload URL input with `/files/from-url` or upload multipart `file` plus `filename` with `/files/upload` (100 MiB ceiling), then retrieve `/files/:file_id`. JSON upload instead uses `file_data` (base64), `filename`, optional `mime_type`/`purpose`; never combine multipart file and base64. Supported native MIME: PDF, JPEG, PNG, GIF, WebP, MP4, QuickTime, AVI, octet-stream. Inline Make reference objects have a 48 KiB limit. `image_refs`, `document_refs`, `video_refs` can use HTTPS/data URIs; `file-*` references work only with the MOON GPT transport. Check each model's modality capabilities and file readiness. The JSON-schema RPC only shapes Make's output editor; it is not a REST endpoint.

| Operation | Method | Path |
|---|---|---|
| `generate` | POST | `/franklab/api/make/dola/generate` |
| `upload_file_from_url` | POST | `/franklab/api/make/dola/files/from-url` |
| `upload_file` | POST | `/franklab/api/make/dola/files/upload` |
| `get_file` | GET | `/franklab/api/make/dola/files/:file_id` |
| `delete_file` | DELETE | `/franklab/api/make/dola/files/:file_id` |
| `task_status` | GET | `/franklab/api/make/dola/tasks/:billing_task_id` |
| `models` | GET | `/franklab/api/make/dola/models` |
| `list_files` | GET | `/franklab/api/make/dola/files` |

### generate

`POST /franklab/api/make/dola/generate`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `prompt` | string | yes | — |
| `async_mode` | boolean | no | Make default: true |
| `system_prompt` | string | no | — |
| `model_key` | string | no | `["moon_gpt","gemini_3_7_flash","gemini_3_5_flash","gemini_3_6_flash","gemini_3_5_flash_lite","opus","sonnet","gpt","gpt5_5","gpt56_sol","gpt56_terra","gpt56_luna","deepseek_pro","deepseek_flash","kimi","grok","alibaba_qwen3_7_max_2026_06_08","alibaba_qwen3_7_plus_2026_05_26"]` |
| `previous_response_id` | string | no | When model_key=moon_gpt |
| `image_refs` | array | no | When model_key=moon_gpt; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=moon_gpt; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `video_refs` | array | no | When model_key=moon_gpt; items: text |
| `conversation_mode` | boolean | no | Make default: false; When model_key=moon_gpt |
| `conversation_id` | string | no | When model_key=moon_gpt |
| `deepwiki_enabled` | boolean | no | Make default: false; When model_key=moon_gpt |
| `image_refs` | array | no | When model_key=gemini_3_7_flash; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=gemini_3_7_flash; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `video_refs` | array | no | When model_key=gemini_3_7_flash; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `thinking_level` | string | no | `["minimal","low","medium","high"]`; When model_key=gemini_3_7_flash |
| `image_refs` | array | no | When model_key=gemini_3_5_flash; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=gemini_3_5_flash; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `video_refs` | array | no | When model_key=gemini_3_5_flash; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `thinking_level` | string | no | `["minimal","low","medium","high"]`; When model_key=gemini_3_5_flash |
| `thinking_budget` | integer | no | When model_key=gemini_3_5_flash |
| `image_refs` | array | no | When model_key=gemini_3_6_flash; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=gemini_3_6_flash; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `video_refs` | array | no | When model_key=gemini_3_6_flash; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `thinking_level` | string | no | `["minimal","low","medium","high"]`; When model_key=gemini_3_6_flash |
| `image_refs` | array | no | When model_key=gemini_3_5_flash_lite; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=gemini_3_5_flash_lite; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `video_refs` | array | no | When model_key=gemini_3_5_flash_lite; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `thinking_level` | string | no | `["minimal","low","medium","high"]`; When model_key=gemini_3_5_flash_lite |
| `image_refs` | array | no | When model_key=opus; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=opus; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `image_refs` | array | no | When model_key=sonnet; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=sonnet; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `image_refs` | array | no | When model_key=gpt; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=gpt; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `image_refs` | array | no | When model_key=gpt5_5; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=gpt5_5; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `image_refs` | array | no | When model_key=gpt56_sol; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=gpt56_sol; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `image_refs` | array | no | When model_key=gpt56_terra; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=gpt56_terra; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `image_refs` | array | no | When model_key=gpt56_luna; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `document_refs` | array | no | When model_key=gpt56_luna; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `image_refs` | array | no | When model_key=kimi; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `video_refs` | array | no | When model_key=kimi; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `image_refs` | array | no | When model_key=grok; `source_type:string, value:string, file_name:string, file_data:string (base64), data_url:string`; items: collection |
| `response_format` | string | no | `["text","json_object","json_schema"]`; Make default: "text" |
| `json_schema_name` | string | conditional | When response_format=json_schema |
| `json_schema` | object | conditional | When response_format=json_schema |
| `max_output_tokens` | integer | no | Make default: 8192 |
| `temperature` | number | no | Make default: 0.7 |

JSON template:

```json
{
  "model_key": "moon_gpt",
  "prompt": "Return the word OK.",
  "max_output_tokens": 16,
  "async_mode": true
}
```

### upload_file_from_url

`POST /franklab/api/make/dola/files/from-url`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `url` | string | yes | — |
| `filename` | string | no | — |
| `purpose` | string | no | Make default: "user_data" |

JSON template:

```json
{
  "url": "https://example.com/owned-synthetic-media.png"
}
```

### upload_file

`POST /franklab/api/make/dola/files/upload`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `filename` | string | yes | — |
| `file_data` | string | no | — |
| `file` | binary | no | — |
| `mime_type` | string | no | — |
| `purpose` | string | no | — |

JSON template:

```json
{
  "filename": "synthetic.png",
  "mime_type": "image/png",
  "file_data": "REPLACE_WITH_BASE64"
}
```

```bash
curl --fail-with-body --max-time 120 -X POST \
  -H "X-API-Key: ${FRANKLAB_KEY:?Set your account key}" \
  -F 'file=@./synthetic.png' -F 'filename=synthetic.png' \
  "$FRANKLAB_BASE_URL/make/dola/files/upload"
```

### get_file

`GET /franklab/api/make/dola/files/:file_id`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `file_id` | string | yes | path |

### delete_file

`DELETE /franklab/api/make/dola/files/:file_id`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `file_id` | string | yes | path |

### task_status

`GET /franklab/api/make/dola/tasks/:billing_task_id`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `billing_task_id` | string | yes | path |

### models

`GET /franklab/api/make/dola/models`

No body or parameters required.

### list_files

`GET /franklab/api/make/dola/files`

No body or parameters required.

## ORKESTR

`lyrics` is temporarily unavailable. If you already have a task ID and polling remains `processing`, contact support with that ID before submitting again.

18 music/text/processing operations plus polling. Select the path; do not send the Make `operation` in JSON. Use a partner API key; legacy service keys are refused. Most Suno operations accept `model`: `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4`. Generate defaults to `V5`, `customMode=false`, `instrumental=false`; the same defaults are not automatically added to other operations.

The REST field **`taskId`** corresponds to Make `sourceTaskId`; `name`/`description` correspond to `personaName`/`personaDescription`. Supply the owned source task/audio identifiers returned by earlier results, not a prompt or arbitrary UUID. Upload cover/extend/mashup require reachable owned `uploadUrl`/`uploadUrl1`/`uploadUrl2`. `customMode=true` needs the chosen model's custom lyrics/style/title fields. `continueAt`, `infillStartS`, `infillEndS`, `vocalStart`, `vocalEnd` are seconds; keep intervals ordered and inside the source audio. Callback routing is managed by the service.

Save the returned FrankLab `data.taskId`; poll `/make/orkestr/v2/tasks/:taskId` every 5 seconds with a bounded deadline. `queued`/`processing` continue; `completed`/`failed` stop. Inspect `data.result` and `data.error`. Media results normally live in `data.result.task_result.audios`, `.videos` or `.images`; lyrics and style are text/JSON, not guaranteed audio URLs. `timestamped_lyrics`, `boost_style`, `generate_persona` return inline results without requiring a poll. `track1_*`/`track2_*` names are Make projections; do not assume they exist in REST.

Lyria uses `model=clip` or `pro`: clip is fixed at 30 seconds, pro is a full track and treats `duration_seconds` as guidance rather than an exact clip length. Optional `output_format=mp3|wav` is supported; default/model limits must be checked before quoting. Inspect `data.audio_url`, `lyrics_text`, `duration_seconds`, `interaction_id` for its result. Billing is account-specific; the absence of a quote route or final-cost field is not a free-operation promise.

| Operation | Method | Path |
|---|---|---|
| `poll` | GET | `/franklab/api/make/orkestr/v2/tasks/:taskId` |
| `generate` | POST | `/franklab/api/make/orkestr/v2/generate` |
| `extend` | POST | `/franklab/api/make/orkestr/v2/extend` |
| `upload_cover` | POST | `/franklab/api/make/orkestr/v2/upload-cover` |
| `upload_extend` | POST | `/franklab/api/make/orkestr/v2/upload-extend` |
| `add_instrumental` | POST | `/franklab/api/make/orkestr/v2/add-instrumental` |
| `add_vocals` | POST | `/franklab/api/make/orkestr/v2/add-vocals` |
| `replace_section` | POST | `/franklab/api/make/orkestr/v2/replace-section` |
| `mashup` | POST | `/franklab/api/make/orkestr/v2/mashup` |
| `lyrics` | POST | `/franklab/api/make/orkestr/v2/lyrics` |
| `timestamped_lyrics` | POST | `/franklab/api/make/orkestr/v2/timestamped-lyrics` |
| `separate_vocals` | POST | `/franklab/api/make/orkestr/v2/separate-vocals` |
| `generate_midi` | POST | `/franklab/api/make/orkestr/v2/generate-midi` |
| `convert_wav` | POST | `/franklab/api/make/orkestr/v2/convert-wav` |
| `music_video` | POST | `/franklab/api/make/orkestr/v2/music-video` |
| `cover_image` | POST | `/franklab/api/make/orkestr/v2/cover-image` |
| `boost_style` | POST | `/franklab/api/make/orkestr/v2/boost-style` |
| `generate_persona` | POST | `/franklab/api/make/orkestr/v2/generate-persona` |
| `lyria_music` | POST | `/franklab/api/make/orkestr/v2/lyria-music` |

### poll

`GET /franklab/api/make/orkestr/v2/tasks/:taskId`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | path |

### generate

`POST /franklab/api/make/orkestr/v2/generate`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model` | string | yes | `["V5","V4_5PLUS","V4_5ALL","V4_5","V4"]` |
| `customMode` | boolean | no | — |
| `instrumental` | boolean | no | — |
| `prompt` | string | yes | — |
| `style` | string | no | — |
| `title` | string | no | — |
| `negativeTags` | string | no | — |
| `vocalGender` | string | no | `["f","m"]` |
| `styleWeight` | number | no | — |
| `weirdnessConstraint` | number | no | — |
| `audioWeight` | number | no | — |
| `personaId` | string | no | — |

JSON template:

```json
{
  "model": "V5",
  "prompt": "A short calm synthetic test."
}
```

### extend

`POST /franklab/api/make/orkestr/v2/extend`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `audioId` | string | yes | — |
| `defaultParamFlag` | boolean | no | — |
| `model` | string | yes | `["V5","V4_5PLUS","V4_5ALL","V4_5","V4"]` |
| `continueAt` | number | no | — |
| `prompt` | string | no | — |
| `style` | string | no | — |
| `title` | string | no | — |
| `negativeTags` | string | no | — |
| `vocalGender` | string | no | `["f","m"]` |
| `personaId` | string | no | — |

JSON template:

```json
{
  "audioId": "REPLACE_WITH_OWNED_AUDIOID",
  "model": "V5"
}
```

### upload_cover

`POST /franklab/api/make/orkestr/v2/upload-cover`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `uploadUrl` | string | yes | — |
| `model` | string | yes | `["V5","V4_5PLUS","V4_5ALL","V4_5","V4"]` |
| `customMode` | boolean | no | — |
| `instrumental` | boolean | no | — |
| `prompt` | string | no | — |
| `style` | string | no | — |
| `title` | string | no | — |
| `negativeTags` | string | no | — |
| `vocalGender` | string | no | `["f","m"]` |
| `personaId` | string | no | — |

JSON template:

```json
{
  "uploadUrl": "https://example.com/owned-synthetic-audio.mp3",
  "model": "V5"
}
```

### upload_extend

`POST /franklab/api/make/orkestr/v2/upload-extend`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `uploadUrl` | string | yes | — |
| `model` | string | yes | `["V5","V4_5PLUS","V4_5ALL","V4_5","V4"]` |
| `defaultParamFlag` | boolean | no | — |
| `instrumental` | boolean | no | — |
| `continueAt` | number | yes | — |
| `prompt` | string | no | — |
| `style` | string | no | — |
| `title` | string | no | — |
| `negativeTags` | string | no | — |
| `vocalGender` | string | no | `["f","m"]` |
| `personaId` | string | no | — |

JSON template:

```json
{
  "uploadUrl": "https://example.com/owned-synthetic-audio.mp3",
  "model": "V5",
  "continueAt": 1
}
```

### add_instrumental

`POST /franklab/api/make/orkestr/v2/add-instrumental`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `uploadUrl` | string | yes | — |
| `title` | string | yes | — |
| `tags` | string | yes | — |
| `negativeTags` | string | no | — |
| `model` | string | no | `["V5","V4_5PLUS","V4_5ALL","V4_5","V4"]` |
| `vocalGender` | string | no | `["f","m"]` |

JSON template:

```json
{
  "uploadUrl": "https://example.com/owned-synthetic-audio.mp3",
  "title": "Synthetic test",
  "tags": "REPLACE_WITH_OWNED_TAGS"
}
```

### add_vocals

`POST /franklab/api/make/orkestr/v2/add-vocals`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `uploadUrl` | string | yes | — |
| `prompt` | string | yes | — |
| `title` | string | yes | — |
| `style` | string | yes | — |
| `negativeTags` | string | no | — |
| `model` | string | no | `["V5","V4_5PLUS","V4_5ALL","V4_5","V4"]` |
| `vocalGender` | string | no | `["f","m"]` |

JSON template:

```json
{
  "uploadUrl": "https://example.com/owned-synthetic-audio.mp3",
  "prompt": "A short calm synthetic test.",
  "title": "Synthetic test",
  "style": "REPLACE_WITH_OWNED_STYLE"
}
```

### replace_section

`POST /franklab/api/make/orkestr/v2/replace-section`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | — |
| `audioId` | string | yes | — |
| `prompt` | string | yes | — |
| `tags` | string | yes | — |
| `title` | string | yes | — |
| `infillStartS` | number | yes | — |
| `infillEndS` | number | yes | — |
| `negativeTags` | string | no | — |
| `fullLyrics` | string | no | — |

JSON template:

```json
{
  "taskId": "REPLACE_WITH_OWNED_TASKID",
  "audioId": "REPLACE_WITH_OWNED_AUDIOID",
  "prompt": "A short calm synthetic test.",
  "tags": "REPLACE_WITH_OWNED_TAGS",
  "title": "Synthetic test",
  "infillStartS": 1,
  "infillEndS": 2
}
```

### mashup

`POST /franklab/api/make/orkestr/v2/mashup`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `uploadUrl1` | string | yes | — |
| `uploadUrl2` | string | yes | — |
| `model` | string | yes | `["V5","V4_5PLUS","V4_5ALL","V4_5","V4"]` |
| `customMode` | boolean | no | — |
| `instrumental` | boolean | no | — |
| `prompt` | string | no | — |
| `style` | string | no | — |
| `title` | string | no | — |
| `negativeTags` | string | no | — |
| `vocalGender` | string | no | `["f","m"]` |

JSON template:

```json
{
  "uploadUrl1": "https://example.com/owned-synthetic-audio.mp3",
  "uploadUrl2": "https://example.com/owned-synthetic-audio-2.mp3",
  "model": "V5"
}
```

### lyrics

`POST /franklab/api/make/orkestr/v2/lyrics`

Temporarily unavailable. Keep existing task IDs for support; use `generate` above to create a song.

### timestamped_lyrics

`POST /franklab/api/make/orkestr/v2/timestamped-lyrics`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | — |
| `audioId` | string | yes | — |

JSON template:

```json
{
  "taskId": "REPLACE_WITH_OWNED_TASKID",
  "audioId": "REPLACE_WITH_OWNED_AUDIOID"
}
```

### separate_vocals

`POST /franklab/api/make/orkestr/v2/separate-vocals`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | — |
| `audioId` | string | yes | — |
| `type` | string | yes | `["separate_vocal","split_stem"]` |

JSON template:

```json
{
  "taskId": "REPLACE_WITH_OWNED_TASKID",
  "audioId": "REPLACE_WITH_OWNED_AUDIOID",
  "type": "separate_vocal"
}
```

### generate_midi

`POST /franklab/api/make/orkestr/v2/generate-midi`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | — |
| `audioId` | string | no | — |

JSON template:

```json
{
  "taskId": "REPLACE_WITH_OWNED_TASKID"
}
```

### convert_wav

`POST /franklab/api/make/orkestr/v2/convert-wav`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | — |
| `audioId` | string | yes | — |

JSON template:

```json
{
  "taskId": "REPLACE_WITH_OWNED_TASKID",
  "audioId": "REPLACE_WITH_OWNED_AUDIOID"
}
```

### music_video

`POST /franklab/api/make/orkestr/v2/music-video`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | — |
| `audioId` | string | yes | — |
| `author` | string | no | — |
| `domainName` | string | no | — |

JSON template:

```json
{
  "taskId": "REPLACE_WITH_OWNED_TASKID",
  "audioId": "REPLACE_WITH_OWNED_AUDIOID"
}
```

### cover_image

`POST /franklab/api/make/orkestr/v2/cover-image`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | — |

JSON template:

```json
{
  "taskId": "REPLACE_WITH_OWNED_TASKID"
}
```

### boost_style

`POST /franklab/api/make/orkestr/v2/boost-style`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `content` | string | yes | — |

JSON template:

```json
{
  "content": "A short calm synthetic test."
}
```

### generate_persona

`POST /franklab/api/make/orkestr/v2/generate-persona`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | — |
| `audioId` | string | yes | — |
| `name` | string | yes | — |
| `description` | string | yes | — |
| `vocalStart` | number | no | — |
| `vocalEnd` | number | no | — |
| `style` | string | no | — |

JSON template:

```json
{
  "taskId": "REPLACE_WITH_OWNED_TASKID",
  "audioId": "REPLACE_WITH_OWNED_AUDIOID",
  "name": "Synthetic test",
  "description": "REPLACE_WITH_OWNED_DESCRIPTION"
}
```

### lyria_music

`POST /franklab/api/make/orkestr/v2/lyria-music`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `model` | string | yes | `["clip","pro"]` |
| `prompt` | string | yes | — |
| `instrumental` | boolean | no | — |
| `lyrics` | string | no | — |
| `language` | string | no | — |
| `genre` | string | no | — |
| `era` | string | no | — |
| `instruments` | string | no | — |
| `song_structure` | string | no | — |
| `timed_events` | string | no | — |
| `vocal_profile` | string | no | — |
| `key_scale` | string | no | — |
| `mood` | string | no | — |
| `duration_seconds` | number | no | — |
| `reference_images` | array | no | `image_url:string`; items: collection |

JSON template:

```json
{
  "model": "clip",
  "prompt": "Calm original instrumental piano.",
  "instrumental": true
}
```

## VOLNA

All 19 Make operations dispatch through `POST /make/volna/tts`; `operation` is required for non-TTS actions and should always be explicit. Choose ElevenLabs dialogue/TTS/Turbo, Google Gemini TTS, Seed Audio, Grok TTS, transcription, effects, isolation, voice tools or dubbing. List voices/models to choose the identifiers for your request. Voice creation/design/save and usage stats reject legacy service keys.

For ElevenLabs, discover `voice_id` via `/v1/elevenlabs/voices-rpc`; for Grok use `/v1/xai/voices-rpc`. RPC output is `data:[{id,name,…}]`; never invent a voice ID. Google `google_tts_mode=single` uses `google_voice_name`; `multi` uses `speaker_1_name`, `speaker_1_voice`, `speaker_2_name`, `speaker_2_voice`, matching labels in `text`. Grok defaults to voice `eve`; `xai_tts_settings` and transcription settings selectors belong only to Make UI.

STT and isolation take an owned `audio_url`; dubbing takes `source_url` and `target_lang`. Pass real JSON booleans and numbers, and `keyterm:["term"]` strings. Voice cloning REST uses `name`/`description` (Make clone_name/clone_description aliases are normalized) and authorized `file_url`. Designed voices are saved separately with `voice_name`/`generated_voice_id`.

Seed Audio uses `text_prompt` (up to 3000 characters), optional at most 3 `references`: each item selects `reference_type=audio|image`, with `speaker`, `audio_url`, `audio_data` or `audio_file_data`/`audio_file_name`, or the corresponding image fields. Supply one reference source, not all alternatives. Audio format mp3/wav/pcm/ogg_opus; sample rate 8000/16000/24000/32000/44100/48000. Speech/loudness rate -50..100, pitch -12..12. REST watermark metadata switch is **boolean `audio_aigc_metadata_enable`**, not Make `audio_aigc_metadata_mode`.

If the response contains `data.taskId`, poll `/make/volna/tasks/:taskId` about every 5 seconds until `completed`/`failed`; a synchronous result or metadata response may have no task ID. Inspect `data.result`, `audio_url`/`audioUrl`, `resultUrl`, `text`, `words`, `segments`, `duration_seconds` and billing fields where supplied. Make audio/status outputs are normalized from different source shapes. Check final `cost_status`, reserve/refund/final amounts and transactions. Do not resubmit a timed-out paid request.

| Operation | Method | Path |
|---|---|---|
| `text-to-dialogue` | POST | `/franklab/api/make/volna/tts` |
| `text-to-speech` | POST | `/franklab/api/make/volna/tts` |
| `text-to-speech-turbo` | POST | `/franklab/api/make/volna/tts` |
| `google-3-1-tts` | POST | `/franklab/api/make/volna/tts` |
| `seed-audio-1-0` | POST | `/franklab/api/make/volna/tts` |
| `xai-text-to-speech` | POST | `/franklab/api/make/volna/tts` |
| `speech-to-text` | POST | `/franklab/api/make/volna/tts` |
| `xai-speech-to-text` | POST | `/franklab/api/make/volna/tts` |
| `google-speech-to-text` | POST | `/franklab/api/make/volna/tts` |
| `sound-effect` | POST | `/franklab/api/make/volna/tts` |
| `audio-isolation` | POST | `/franklab/api/make/volna/tts` |
| `voice-list` | POST | `/franklab/api/make/volna/tts` |
| `xai-voice-list` | POST | `/franklab/api/make/volna/tts` |
| `voice-clone` | POST | `/franklab/api/make/volna/tts` |
| `voice-design` | POST | `/franklab/api/make/volna/tts` |
| `voice-design-save` | POST | `/franklab/api/make/volna/tts` |
| `dubbing` | POST | `/franklab/api/make/volna/tts` |
| `usage-stats` | POST | `/franklab/api/make/volna/tts` |
| `models-list` | POST | `/franklab/api/make/volna/tts` |
| `poll` | GET | `/franklab/api/make/volna/tasks/:taskId` |
| `getVoices RPC` | GET | `/franklab/api/v1/elevenlabs/voices-rpc` |
| `getGrokVoices RPC` | GET | `/franklab/api/v1/xai/voices-rpc` |

### text-to-dialogue

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"text-to-dialogue"` |
| `text` | string | yes | — |
| `voice_id` | string | yes | — |
| `voice_id_2` | string | no | — |
| `seed` | number | no | — |

JSON template:

```json
{
  "operation": "text-to-dialogue",
  "text": "A short calm synthetic test.",
  "voice_id": "REPLACE_WITH_OWNED_VOICE_ID"
}
```

### text-to-speech

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"text-to-speech"` |
| `text` | string | yes | — |
| `voice_id` | string | yes | — |
| `model_id` | string | no | `["eleven_multilingual_v2","eleven_flash_v2_5","eleven_v3"]` |
| `language_code` | string | no | — |
| `stability` | number | no | — |
| `similarity_boost` | number | no | — |
| `style` | number | no | — |
| `speed` | number | no | — |
| `output_format` | string | no | `["mp3_44100_128","mp3_44100_192","pcm_16000","pcm_22050","pcm_44100"]` |

JSON template:

```json
{
  "operation": "text-to-speech",
  "text": "A short calm synthetic test.",
  "voice_id": "REPLACE_WITH_OWNED_VOICE_ID"
}
```

### text-to-speech-turbo

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"text-to-speech-turbo"` |
| `text` | string | yes | — |
| `voice_id` | string | yes | — |
| `language_code` | string | no | — |
| `stability` | number | no | — |
| `similarity_boost` | number | no | — |
| `style` | number | no | — |
| `speed` | number | no | — |

JSON template:

```json
{
  "operation": "text-to-speech-turbo",
  "text": "A short calm synthetic test.",
  "voice_id": "REPLACE_WITH_OWNED_VOICE_ID"
}
```

### google-3-1-tts

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"google-3-1-tts"` |
| `google_tts_mode` | string | yes | `["single","multi"]` |
| `text` | string | conditional | When google_tts_mode=single |
| `google_voice_name` | string | conditional | `["Achernar","Achird","Algenib","Algieba","Alnilam","Aoede","Autonoe","Callirrhoe","Charon","Despina","Enceladus","Erinome","Fenrir","Gacrux","Iapetus","Kore","Laomedeia","Leda","Orus","Puck","Pulcherrima","Rasalgethi","Sadachbia","Sadaltager","Schedar","Sulafat","Umbriel","Vindemiatrix","Zephyr","Zubenelgenubi"]`; When google_tts_mode=single |
| `style_prompt` | string | no | When google_tts_mode=single |
| `output_format` | string | no | `["wav_24000_16","mp3_44100_128","mp3_44100_192","opus_48000_64"]`; When google_tts_mode=single |
| `request_id` | string | no | When google_tts_mode=single |
| `text` | string | conditional | When google_tts_mode=multi |
| `speaker_1_name` | string | conditional | When google_tts_mode=multi |
| `speaker_1_voice` | string | conditional | `["Achernar","Achird","Algenib","Algieba","Alnilam","Aoede","Autonoe","Callirrhoe","Charon","Despina","Enceladus","Erinome","Fenrir","Gacrux","Iapetus","Kore","Laomedeia","Leda","Orus","Puck","Pulcherrima","Rasalgethi","Sadachbia","Sadaltager","Schedar","Sulafat","Umbriel","Vindemiatrix","Zephyr","Zubenelgenubi"]`; When google_tts_mode=multi |
| `speaker_2_name` | string | conditional | When google_tts_mode=multi |
| `speaker_2_voice` | string | conditional | `["Achernar","Achird","Algenib","Algieba","Alnilam","Aoede","Autonoe","Callirrhoe","Charon","Despina","Enceladus","Erinome","Fenrir","Gacrux","Iapetus","Kore","Laomedeia","Leda","Orus","Puck","Pulcherrima","Rasalgethi","Sadachbia","Sadaltager","Schedar","Sulafat","Umbriel","Vindemiatrix","Zephyr","Zubenelgenubi"]`; When google_tts_mode=multi |
| `style_prompt` | string | no | When google_tts_mode=multi |
| `output_format` | string | no | `["wav_24000_16","mp3_44100_128","mp3_44100_192","opus_48000_64"]`; When google_tts_mode=multi |
| `request_id` | string | no | When google_tts_mode=multi |

JSON template:

```json
{
  "operation": "google-3-1-tts",
  "text": "Hello.",
  "google_tts_mode": "single",
  "google_voice_name": "Kore"
}
```

### seed-audio-1-0

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"seed-audio-1-0"` |
| `text_prompt` | string | yes | — |
| `references` | array | no | `reference_type, speaker, audio_url/audio_data/audio_file_data, audio_file_name, image_url/image_data/image_file_data, image_file_name`; items: collection |
| `audio_format` | string | no | `["mp3","wav","pcm","ogg_opus"]`; Make default: "mp3" |
| `audio_sample_rate` | string | no | `["8000","16000","24000","32000","44100","48000"]`; Make default: "44100" |
| `audio_speech_rate` | number | no | — |
| `audio_loudness_rate` | number | no | — |
| `audio_pitch_rate` | number | no | — |
| `audio_enable_subtitle` | boolean | no | — |
| `audio_aigc_watermark` | boolean | no | — |
| `audio_aigc_metadata_enable` | boolean | no | `[false,true]`; Make default: false |
| `audio_content_producer` | string | no | When audio_aigc_metadata_enable=true |
| `audio_produce_id` | string | no | When audio_aigc_metadata_enable=true |
| `audio_content_propagator` | string | no | When audio_aigc_metadata_enable=true |
| `audio_propagate_id` | string | no | When audio_aigc_metadata_enable=true |

JSON template:

```json
{
  "operation": "seed-audio-1-0",
  "text_prompt": "A short calm synthetic test."
}
```

### xai-text-to-speech

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"xai-text-to-speech"` |
| `text` | string | yes | — |
| `voice_id` | string | no | Make default: "eve" |
| `language` | string | no | `["auto","ru","en","es","de","fr","it","ja","pt-BR"]`; Make default: "auto" |
| `output_format` | string | no | `["mp3_44100_128","mp3_44100_192","wav_24000","pcm_24000"]`; Make default: "mp3_44100_128" |
| `with_timestamps` | boolean | no | — |
| `speed` | string | no | `["0.8","0.9","1","1.1","1.2"]`; Make default: "1" |

JSON template:

```json
{
  "operation": "xai-text-to-speech",
  "text": "Hello.",
  "voice_id": "eve",
  "output_format": "mp3_44100_128"
}
```

### speech-to-text

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"speech-to-text"` |
| `audio_url` | string | yes | — |
| `language_code` | string | no | — |
| `diarize` | boolean | no | — |
| `num_speakers` | number | no | — |

JSON template:

```json
{
  "operation": "speech-to-text",
  "audio_url": "https://example.com/owned-synthetic-audio.mp3"
}
```

### xai-speech-to-text

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"xai-speech-to-text"` |
| `audio_url` | string | yes | — |
| `language` | string | no | `["auto","ru","en","es","de","fr","it","ja","pt-BR"]`; Make default: "auto" |
| `format` | boolean | no | — |
| `diarize` | boolean | no | — |
| `filler_words` | boolean | no | — |
| `chunked_recovery` | boolean | no | — |
| `keyterm` | array | no | items: string |

JSON template:

```json
{
  "operation": "xai-speech-to-text",
  "audio_url": "https://example.com/owned-synthetic-audio.mp3"
}
```

### google-speech-to-text

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"google-speech-to-text"` |
| `audio_url` | string | yes | — |
| `language_code` | string | no | `["auto","ru-RU","en-US","en-GB","de-DE","fr-FR","es-ES","it-IT","pt-BR","ja-JP","ko-KR","uk-UA"]`; Make default: "auto" |
| `diarize` | boolean | no | — |
| `format` | boolean | no | — |
| `keyterm` | array | no | items: string |

JSON template:

```json
{
  "operation": "google-speech-to-text",
  "audio_url": "https://example.com/owned-synthetic-audio.mp3"
}
```

### sound-effect

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"sound-effect"` |
| `text` | string | yes | — |
| `duration_seconds` | number | no | — |
| `prompt_influence` | number | no | — |

JSON template:

```json
{
  "operation": "sound-effect",
  "text": "A short calm synthetic test."
}
```

### audio-isolation

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"audio-isolation"` |
| `audio_url` | string | yes | — |

JSON template:

```json
{
  "operation": "audio-isolation",
  "audio_url": "https://example.com/owned-synthetic-audio.mp3"
}
```

### voice-list

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"voice-list"` |

JSON template:

```json
{
  "operation": "voice-list"
}
```

### xai-voice-list

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"xai-voice-list"` |

JSON template:

```json
{
  "operation": "xai-voice-list"
}
```

### voice-clone

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"voice-clone"` |
| `name` | string | yes | — |
| `description` | string | no | — |
| `file_url` | string | yes | — |

JSON template:

```json
{
  "operation": "voice-clone",
  "name": "Synthetic test",
  "file_url": "https://example.com/owned-synthetic-audio.mp3"
}
```

### voice-design

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"voice-design"` |
| `voice_description` | string | yes | — |
| `design_text` | string | no | — |
| `guidance_scale` | number | no | — |
| `should_enhance` | boolean | no | — |

JSON template:

```json
{
  "operation": "voice-design",
  "voice_description": "REPLACE_WITH_OWNED_VOICE_DESCRIPTION"
}
```

### voice-design-save

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"voice-design-save"` |
| `voice_name` | string | yes | — |
| `generated_voice_id` | string | yes | — |
| `voice_description` | string | no | — |

JSON template:

```json
{
  "operation": "voice-design-save",
  "voice_name": "REPLACE_WITH_OWNED_VOICE_NAME",
  "generated_voice_id": "REPLACE_WITH_OWNED_GENERATED_VOICE_ID"
}
```

### dubbing

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"dubbing"` |
| `source_url` | string | yes | — |
| `target_lang` | string | yes | — |
| `source_lang` | string | no | — |
| `dubbing_name` | string | no | — |
| `num_speakers` | number | no | — |

JSON template:

```json
{
  "operation": "dubbing",
  "source_url": "https://example.com/owned-synthetic-audio.mp3",
  "target_lang": "en"
}
```

### usage-stats

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"usage-stats"` |

JSON template:

```json
{
  "operation": "usage-stats"
}
```

### models-list

`POST /franklab/api/make/volna/tts`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `operation` | string | yes | `"models-list"` |

JSON template:

```json
{
  "operation": "models-list"
}
```

### poll

`GET /franklab/api/make/volna/tasks/:taskId`

| REST field | Type | Required | Values / conditions |
|---|---|---|---|
| `taskId` | string | yes | path |

### getVoices RPC

`GET /franklab/api/v1/elevenlabs/voices-rpc`

No body or parameters required.

### getGrokVoices RPC

`GET /franklab/api/v1/xai/voices-rpc`

No body or parameters required.

## Supporting connection and result routes

| Module | Method and path | Parameters |
|---|---|---|
| JUPITER | `GET /franklab/api/v1/images/omni-image` | — |
| KUSOK v.2 | `GET /franklab/api/v1/general/advanced-custom-elements` | — |
| ORKESTR | `GET /franklab/api/v1/suno/generate/record-info` | `taskId` (query) |
| VOLNA | `GET /franklab/api/make/volna/dubbing/:dubbingId` | `dubbingId` (path) |
| VOLNA | `GET /franklab/api/make/volna/dubbing/:dubbingId/audio/:languageCode` | `dubbingId` (path), `languageCode` (path) |

A request with a nonexistent task ID returns 404. Use the matching operation status route for newly submitted tasks.

## Next step

Choose one operation, check your key/balance/available quote, run a minimal request with your synthetic inputs and save the ID. Then verify the final result and charge. [Integration sequence](/en/docs/integration) · [Errors](/en/docs/errors) · [Support](/en/docs/contacts).
