# Extend Music
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/extend
POST https://api.apimart.ai/v1/music/generations/extendFlowMusic
Flow Music continues a previously generated audio clip. Extends the music from a specified time point according to an editing instruction
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/extendFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"clip_id": "abc123-def456",
"extend_from_s": 30,
"extend_s": 60,
"instruction": "Continue the verse melody, add strings"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/extendFlowMusic"
payload = {
"model": "flowmusic",
"clip_id": "abc123-def456",
"extend_from_s": 30,
"extend_s": 60,
"instruction": "Continue the verse melody, add strings"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/extendFlowMusic";
const payload = {
model: "flowmusic",
clip_id: "abc123-def456",
extend_from_s: 30,
extend_s: 60,
instruction: "Continue the verse melody, add strings"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVCYB70YJ1WY9X22RVYRNP"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "clip_id is required",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
Source music clip\_id, from a successful task's `result.music[].clip_id`
The source task must have succeeded. External audio can first be imported via [Upload Audio](./upload-audio) to obtain a clip\_id.
Time point (seconds) to start the extension from
Cannot exceed the source clip's duration
Extension duration (seconds)
Maximum: `164` seconds
Editing instruction for the extended music
Example: `"Continue the verse melody, add strings"`
Title of the extended music
Random seed, used to reproduce results
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Extend 60 seconds from the chorus
```json theme={null}
{
"model": "flowmusic",
"clip_id": "abc123-def456",
"extend_from_s": 30,
"extend_s": 60,
"instruction": "Continue the verse melody, add strings"
}
```
**Query Task Results**
Music extension is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results. The extension output is a **new** `clip_id`; use the new clip\_id for subsequent operations.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVCYB70YJ1WY9X22RVYRNP",
"status": "completed",
"progress": 100,
"created": 1783413242,
"completed": 1783413292,
"actual_time": 50,
"cost": 0.048,
"credits_cost": 0.48,
"result": {
"music": [
{
"clip_id": "d2f589ea-5390-4e83-8e2f-4517420408fa",
"title": "Untitled (Extended)",
"duration_seconds": "39.95733333",
"create_time": "2026-07-07T08:34:33.240020Z",
"lyrics": "waking up to the morning light,\n...",
"lyrics_id": "0452451b-9e54-5d9f-8437-8bff97c7bbc8",
"lyrics_timing_markers": [[0, 12], [129, 20]],
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_d2f589ea.m4a",
"wav_url": "https://cdn.apimart.ai/audio/flowmusic_d2f589ea.wav",
"image_url": "https://cdn.apimart.ai/image/flowmusic_d2f589ea_cover.jpg"
}
]
}
}
}
```
# Lyria 3.5 Extend Music
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/extend-lyria-3-5
POST https://api.apimart.ai/v1/music/generations/extendFlowMusic
Use Lyria 3.5 to extend previously generated music from a specified time point
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/extendFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"version": "lyria-3.5",
"clip_id": "abc123-def456",
"extend_from_s": 30,
"extend_s": 60,
"instruction": "Continue the verse melody, add strings"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/extendFlowMusic"
payload = {
"model": "flowmusic",
"version": "lyria-3.5",
"clip_id": "abc123-def456",
"extend_from_s": 30,
"extend_s": 60,
"instruction": "Continue the verse melody, add strings"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/extendFlowMusic";
const payload = {
model: "flowmusic",
version: "lyria-3.5",
clip_id: "abc123-def456",
extend_from_s: 30,
extend_s: 60,
instruction: "Continue the verse melody, add strings"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVCYB70YJ1WY9X22RVYRNP"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "clip_id is required",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
Model version, **must be `"lyria-3.5"`**
Lyria 3.5 still uses `flowmusic` as the model name. Do not change `model` to `lyria-3.5` or `flowmusic-lyria-3.5`.
Source music clip\_id, from a successful task's `result.music[].clip_id`
The source task must have succeeded. External audio can first be imported via [Upload Audio](./upload-audio) to obtain a clip\_id.
Time point (seconds) to start the extension from
Cannot exceed the source clip's duration
Extension duration (seconds)
Maximum: `164` seconds
Editing instruction for the extended music
Example: `"Continue the verse melody, add strings"`
Title of the extended music
Random seed, used to reproduce results
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Extend 60 seconds from the chorus
```json theme={null}
{
"model": "flowmusic",
"version": "lyria-3.5",
"clip_id": "abc123-def456",
"extend_from_s": 30,
"extend_s": 60,
"instruction": "Continue the verse melody, add strings"
}
```
**Query Task Results**
Music extension is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results. The extension output is a **new** `clip_id`; use the new clip\_id for subsequent operations.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVCYB70YJ1WY9X22RVYRNP",
"status": "completed",
"progress": 100,
"created": 1783413242,
"completed": 1783413292,
"actual_time": 50,
"cost": 0.048,
"credits_cost": 0.48,
"result": {
"music": [
{
"clip_id": "d2f589ea-5390-4e83-8e2f-4517420408fa",
"title": "Untitled (Extended)",
"duration_seconds": "39.95733333",
"create_time": "2026-07-07T08:34:33.240020Z",
"lyrics": "waking up to the morning light,\n...",
"lyrics_id": "0452451b-9e54-5d9f-8437-8bff97c7bbc8",
"lyrics_timing_markers": [[0, 12], [129, 20]],
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_d2f589ea.m4a",
"wav_url": "https://cdn.apimart.ai/audio/flowmusic_d2f589ea.wav",
"image_url": "https://cdn.apimart.ai/image/flowmusic_d2f589ea_cover.jpg"
}
]
}
}
}
```
# Generate Lyrics
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/lyrics
POST https://api.apimart.ai/v1/music/generations/lyricsFlowMusic
Flow Music generates lyrics from a prompt. The result can be filled into the lyrics field of the Generate Music endpoint
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/lyricsFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"prompt": "A rock song about perseverance"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/lyricsFlowMusic"
payload = {
"model": "flowmusic",
"prompt": "A rock song about perseverance"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/lyricsFlowMusic";
const payload = {
model: "flowmusic",
prompt: "A rock song about perseverance"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVCX91HYHSTHZ0NC1SRFW1"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "model is required",
"type": "invalid_request",
"param": "",
"code": "model_required"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
Prompt for generating lyrics, **≤ 3000 characters**
It is recommended to describe the song's theme, style, and mood to get better-fitting lyrics
Example: `"A rock song about perseverance"`
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Generate lyrics by theme
```json theme={null}
{
"model": "flowmusic",
"prompt": "A rock song about perseverance"
}
```
### Scenario 2: Fill generated lyrics into a song
First generate lyrics; once done, take the `title` and `lyrics` from `result.lyrics[0]` and fill them into the [Generate Music](./music) endpoint:
```json theme={null}
{
"model": "flowmusic",
"title": "Perseverance",
"lyrics": "[Verse 1]\nEven the longest night turns to dawn\n...",
"sound_prompt": "energetic rock with electric guitar"
}
```
**Query Task Results**
Lyrics generation is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVCX91HYHSTHZ0NC1SRFW1",
"status": "completed",
"progress": 100,
"created": 1783413241,
"completed": 1783413284,
"actual_time": 43,
"cost": 0.016,
"credits_cost": 0.16,
"result": {
"lyrics": [
{
"title": "Bleached",
"lyrics": "[Intro]\n(Check)\n(One two)\n\n[Verse 1]\nThe birds are..."
}
]
}
}
}
```
# Generate Music
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/music
POST https://api.apimart.ai/v1/music/generations
Flow Music text-to-music generation. Supports style prompts / lyrics / BPM / duration control, generating one track per request
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"title": "My Song",
"sound_prompt": "upbeat pop music with piano",
"bpm": "120",
"length": 60
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations"
payload = {
"model": "flowmusic",
"title": "My Song",
"sound_prompt": "upbeat pop music with piano",
"bpm": "120",
"length": 60
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations";
const payload = {
model: "flowmusic",
title: "My Song",
sound_prompt: "upbeat pop music with piano",
bpm: "120",
length: 60
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8AYYM6R03TGZ3Q2P0TZVNPX"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "sound_prompt and lyrics cannot both be empty",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
Music style or sound description prompt
Example: `"upbeat pop music with piano"`
`sound_prompt` and `lyrics` **cannot both be empty** (at least one is required). Each request generates only one track.
Lyrics text; you can first obtain lyrics from the [Generate Lyrics](./lyrics) endpoint and fill them in here
Example: `"[Verse 1]\nEven the longest night turns to dawn\n..."`
Title of the generated music
BPM (beats per minute), must be ≥ 1
Example: `"120"`
Generation duration (seconds)
Supported range: `1` \~ `240` seconds
Random seed, used to reproduce results
Passing the same seed value with the same request produces similar results, but exact reproducibility is not guaranteed.
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Generate from a style prompt only
```json theme={null}
{
"model": "flowmusic",
"title": "My Song",
"sound_prompt": "upbeat pop music with piano",
"bpm": "120",
"length": 60
}
```
### Scenario 2: Lyrics + style to a full song
```json theme={null}
{
"model": "flowmusic",
"title": "Perseverance",
"lyrics": "[Verse 1]\nEven the longest night turns to dawn\n...",
"sound_prompt": "energetic rock with electric guitar",
"length": 120
}
```
**Query Task Results**
Music generation is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVB61E28THHFBSYXWA4FAJ",
"status": "completed",
"progress": 100,
"created": 1783413184,
"completed": 1783413236,
"actual_time": 52,
"cost": 0.048,
"credits_cost": 0.48,
"result": {
"music": [
{
"clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c",
"title": "Regression Song",
"duration_seconds": "181.70666667",
"create_time": "2026-07-07T08:33:32.854073Z",
"lyrics": "[Verse 1]\nWaking up to the morning light,\n...",
"lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1",
"lyrics_timing_markers": [[10, 12], [212, 36]],
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4.m4a",
"wav_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4.wav",
"image_url": "https://cdn.apimart.ai/image/flowmusic_a41aade4_cover.jpg"
}
]
}
}
}
```
# Lyria 3.5 Generate Music
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/music-lyria-3-5
POST https://api.apimart.ai/v1/music/generations
Use Lyria 3.5 for Flow Music text-to-music generation with style prompts, lyrics, BPM, and duration control
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"version": "lyria-3.5",
"title": "My Song",
"sound_prompt": "upbeat pop music with piano",
"bpm": "120",
"length": 60
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations"
payload = {
"model": "flowmusic",
"version": "lyria-3.5",
"title": "My Song",
"sound_prompt": "upbeat pop music with piano",
"bpm": "120",
"length": 60
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations";
const payload = {
model: "flowmusic",
version: "lyria-3.5",
title: "My Song",
sound_prompt: "upbeat pop music with piano",
bpm: "120",
length: 60
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8AYYM6R03TGZ3Q2P0TZVNPX"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "sound_prompt and lyrics cannot both be empty",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
Model version, **must be `"lyria-3.5"`**
Lyria 3.5 still uses `flowmusic` as the model name. Do not change `model` to `lyria-3.5` or `flowmusic-lyria-3.5`.
Music style or sound description prompt
Example: `"upbeat pop music with piano"`
`sound_prompt` and `lyrics` **cannot both be empty** (at least one is required). Each request generates only one track.
Lyrics text; you can first obtain lyrics from the [Generate Lyrics](./lyrics) endpoint and fill them in here
Example: `"[Verse 1]\nEven the longest night turns to dawn\n..."`
Title of the generated music
BPM (beats per minute), must be ≥ 1
Example: `"120"`
Generation duration (seconds)
Supported range: `1` \~ `240` seconds
Random seed, used to reproduce results
Passing the same seed value with the same request produces similar results, but exact reproducibility is not guaranteed.
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Generate from a style prompt only
```json theme={null}
{
"model": "flowmusic",
"version": "lyria-3.5",
"title": "My Song",
"sound_prompt": "upbeat pop music with piano",
"bpm": "120",
"length": 60
}
```
### Scenario 2: Lyrics + style to a full song
```json theme={null}
{
"model": "flowmusic",
"version": "lyria-3.5",
"title": "Perseverance",
"lyrics": "[Verse 1]\nEven the longest night turns to dawn\n...",
"sound_prompt": "energetic rock with electric guitar",
"length": 120
}
```
**Query Task Results**
Music generation is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVB61E28THHFBSYXWA4FAJ",
"status": "completed",
"progress": 100,
"created": 1783413184,
"completed": 1783413236,
"actual_time": 52,
"cost": 0.048,
"credits_cost": 0.48,
"result": {
"music": [
{
"clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c",
"title": "Regression Song",
"duration_seconds": "181.70666667",
"create_time": "2026-07-07T08:33:32.854073Z",
"lyrics": "[Verse 1]\nWaking up to the morning light,\n...",
"lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1",
"lyrics_timing_markers": [[10, 12], [212, 36]],
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4.m4a",
"wav_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4.wav",
"image_url": "https://cdn.apimart.ai/image/flowmusic_a41aade4_cover.jpg"
}
]
}
}
}
```
# TTS Text-to-Speech
Source: https://docs.apimart.ai/en/api-reference/audios/tts
POST https://api.apimart.ai/v1/audio/speech
- Support multiple voice models and voice selections
- Output high-quality audio formats: wav, opus, aac, flac, pcm
- Maximum input text of 4096 characters
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/audio/speech \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gpt-4o-mini-tts",
"input": "The quick brown fox jumps over the lazy dog.",
"voice": "alloy",
"response_format": "opus",
"speed": 1.0
}' \
--output speech.opus
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/audio/speech"
payload = {
"model": "gpt-4o-mini-tts",
"input": "The quick brown fox jumps over the lazy dog.",
"voice": "alloy",
"response_format": "opus",
"speed": 1.0
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
with open("speech.opus", "wb") as f:
f.write(response.content)
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/audio/speech";
const payload = {
model: "gpt-4o-mini-tts",
input: "The quick brown fox jumps over the lazy dog.",
voice: "alloy",
response_format: "opus",
speed: 1.0
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'speech.opus';
a.click();
})
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
func main() {
url := "https://api.apimart.ai/v1/audio/speech"
payload := map[string]interface{}{
"model": "gpt-4o-mini-tts",
"input": "The quick brown fox jumps over the lazy dog.",
"voice": "alloy",
"response_format": "opus",
"speed": 1.0,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := os.Create("speech.opus")
defer out.Close()
io.Copy(out, resp.Body)
fmt.Println("Audio saved to speech.opus")
}
```
```java Java theme={null}
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/audio/speech";
String json = """
{
"model": "gpt-4o-mini-tts",
"input": "The quick brown fox jumps over the lazy dog.",
"voice": "alloy",
"response_format": "opus",
"speed": 1.0
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofInputStream());
try (FileOutputStream fos = new FileOutputStream("speech.opus")) {
response.body().transferTo(fos);
}
}
}
```
```php PHP theme={null}
"gpt-4o-mini-tts",
"input" => "The quick brown fox jumps over the lazy dog.",
"voice" => "alloy",
"response_format" => "opus",
"speed" => 1.0
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
file_put_contents("speech.opus", $response);
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'uri'
require 'json'
url = URI("https://api.apimart.ai/v1/audio/speech")
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = {
model: "gpt-4o-mini-tts",
input: "The quick brown fox jumps over the lazy dog.",
voice: "alloy",
response_format: "opus",
speed: 1.0
}.to_json
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
response = http.request(request)
File.open("speech.opus", "wb") do |file|
file.write(response.body)
end
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/audio/speech")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let payload: [String: Any] = [
"model": "gpt-4o-mini-tts",
"input": "The quick brown fox jumps over the lazy dog.",
"voice": "alloy",
"response_format": "opus",
"speed": 1.0
]
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data {
let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
.appendingPathComponent("speech.opus")
try? data.write(to: fileURL)
print("Audio saved to \(fileURL)")
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/audio/speech";
var payload = new
{
model = "gpt-4o-mini-tts",
input = "The quick brown fox jumps over the lazy dog.",
voice = "alloy",
response_format = "opus",
speed = 1.0
};
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var audioBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("speech.opus", audioBytes);
Console.WriteLine("Audio saved to speech.opus");
}
}
```
```c C theme={null}
#include
#include
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
return fwrite(ptr, size, nmemb, stream);
}
int main(void) {
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
FILE *fp = fopen("speech.opus", "wb");
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
const char *json_data = "{\"model\":\"gpt-4o-mini-tts\",\"input\":\"The quick brown fox jumps over the lazy dog.\",\"voice\":\"alloy\",\"response_format\":\"opus\",\"speed\":1.0}";
curl_easy_setopt(curl, CURLOPT_URL, "https://api.apimart.ai/v1/audio/speech");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
fclose(fp);
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/audio/speech"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
NSDictionary *payload = @{
@"model": @"gpt-4o-mini-tts",
@"input": @"The quick brown fox jumps over the lazy dog.",
@"voice": @"alloy",
@"response_format": @"opus",
@"speed": @1.0
};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:nil];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"speech.opus"];
[data writeToFile:filePath atomically:YES];
NSLog(@"Audio saved to %@", filePath);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/audio/speech"
let json_body = `Assoc [
("model", `String "gpt-4o-mini-tts");
("input", `String "The quick brown fox jumps over the lazy dog.");
("voice", `String "alloy");
("response_format", `String "opus");
("speed", `Float 1.0)
]
let () =
let body = Cohttp_lwt.Body.of_string (Yojson.Safe.to_string json_body) in
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
Lwt_main.run (
Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
let oc = open_out_bin "speech.opus" in
output_string oc body_str;
close_out oc;
print_endline "Audio saved to speech.opus"
)
```
```dart Dart theme={null}
import 'dart:io';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/audio/speech');
final payload = {
'model': 'gpt-4o-mini-tts',
'input': 'The quick brown fox jumps over the lazy dog.',
'voice': 'alloy',
'response_format': 'opus',
'speed': 1.0
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json'
},
body: jsonEncode(payload)
);
await File('speech.opus').writeAsBytes(response.bodyBytes);
print('Audio saved to speech.opus');
}
```
```r R theme={null}
library(httr)
url <- "https://api.apimart.ai/v1/audio/speech"
payload <- list(
model = "gpt-4o-mini-tts",
input = "The quick brown fox jumps over the lazy dog.",
voice = "alloy",
response_format = "opus",
speed = 1.0
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = payload,
encode = "json"
)
writeBin(content(response, "raw"), "speech.opus")
cat("Audio saved to speech.opus\n")
```
```binary 200 theme={null}
Binary audio data stream
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please recharge and try again",
"type": "payment_required"
}
}
```
```json 413 theme={null}
{
"error": {
"code": 413,
"message": "Input text exceeds limit (maximum 4096 characters)",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway, server temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All APIs require Bearer Token authentication
Get API Key:
Visit [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
TTS model name
Available models:
* `gpt-4o-mini-tts` - GPT-4o Mini TTS model
Example: `"gpt-4o-mini-tts"`
The text to convert to speech
Maximum length: 4096 characters
Example: `"The quick brown fox jumps over the lazy dog."`
Voice selection
Available voices:
* `alloy` - Neutral, balanced voice
* `echo` - Male, calm voice
* `fable` - British, narrative voice
* `onyx` - Male, deep voice
* `nova` - Female, energetic voice
* `shimmer` - Female, gentle voice
Example: `"alloy"`
Audio output format
Supported formats:
* `wav` - WAV format, uncompressed (default)
* `opus` - Opus format, for internet streaming
* `aac` - AAC format
* `flac` - FLAC format, lossless compression
* `pcm` - PCM format, raw audio data
Example: `"wav"`
Speech playback speed
Range: 0.25 to 4.0
* `0.25` - Slowest speed (1/4x)
* `1.0` - Normal speed (default)
* `4.0` - Fastest speed (4x)
Example: `1.0`
## Response
Returns binary audio data stream on success, which can be saved as an audio file or played directly.
Returns JSON formatted error information on error, including error code, message, and type.
# Whisper-1 Audio Transcription
Source: https://docs.apimart.ai/en/api-reference/audios/whisper-1
POST https://api.apimart.ai/v1/audio/transcriptions
- Supports speech recognition in 99 languages
- Multiple output formats: json, text, srt, vtt, etc.
- Maximum file size 25 MB
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/audio/transcriptions \
--header 'Authorization: Bearer ' \
--header 'Content-Type: multipart/form-data' \
--form 'file=@/path/to/audio.mp3' \
--form 'model=whisper-1' \
--form 'language=en' \
--form 'response_format=json'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/audio/transcriptions"
files = {
"file": open("/path/to/audio.mp3", "rb")
}
data = {
"model": "whisper-1",
"language": "en",
"response_format": "json"
}
headers = {
"Authorization": "Bearer "
}
response = requests.post(url, files=files, data=data, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/audio/transcriptions";
const formData = new FormData();
formData.append("file", audioFile);
formData.append("model", "whisper-1");
formData.append("language", "en");
formData.append("response_format", "json");
const headers = {
"Authorization": "Bearer "
};
fetch(url, {
method: "POST",
headers: headers,
body: formData
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
func main() {
url := "https://api.apimart.ai/v1/audio/transcriptions"
file, _ := os.Open("/path/to/audio.mp3")
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("file", "audio.mp3")
io.Copy(part, file)
writer.WriteField("model", "whisper-1")
writer.WriteField("language", "en")
writer.WriteField("response_format", "json")
writer.Close()
req, _ := http.NewRequest("POST", url, body)
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", writer.FormDataContentType())
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
responseBody, _ := io.ReadAll(resp.Body)
fmt.Println(string(responseBody))
}
```
```java Java theme={null}
import java.io.File;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/audio/transcriptions";
File audioFile = new File("/path/to/audio.mp3");
// Use Apache HttpClient or OkHttp library for multipart/form-data requests
}
}
```
```php PHP theme={null}
$file,
"model" => "whisper-1",
"language" => "en",
"response_format" => "json"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer "
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'uri'
url = URI("https://api.apimart.ai/v1/audio/transcriptions")
File.open('/path/to/audio.mp3', 'rb') do |file|
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
form_data = [
['file', file, { filename: 'audio.mp3', content_type: 'audio/mpeg' }],
['model', 'whisper-1'],
['language', 'en'],
['response_format', 'json']
]
request.set_form form_data, 'multipart/form-data'
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
response = http.request(request)
puts response.body
end
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/audio/transcriptions")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var body = Data()
// Add file
let fileURL = URL(fileURLWithPath: "/path/to/audio.mp3")
if let fileData = try? Data(contentsOf: fileURL) {
body.append("--\(boundary)\r\n".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"audio.mp3\"\r\n".data(using: .utf8)!)
body.append("Content-Type: audio/mpeg\r\n\r\n".data(using: .utf8)!)
body.append(fileData)
body.append("\r\n".data(using: .utf8)!)
}
// Add other fields
let fields = ["model": "whisper-1", "language": "en", "response_format": "json"]
for (key, value) in fields {
body.append("--\(boundary)\r\n".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!)
body.append("\(value)\r\n".data(using: .utf8)!)
}
body.append("--\(boundary)--\r\n".data(using: .utf8)!)
request.httpBody = body
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/audio/transcriptions";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
using var form = new MultipartFormDataContent();
var fileStream = File.OpenRead("/path/to/audio.mp3");
form.Add(new StreamContent(fileStream), "file", "audio.mp3");
form.Add(new StringContent("whisper-1"), "model");
form.Add(new StringContent("en"), "language");
form.Add(new StringContent("json"), "response_format");
var response = await client.PostAsync(url, form);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
struct curl_httppost *formpost = NULL;
struct curl_httppost *lastptr = NULL;
struct curl_slist *headers = NULL;
curl_global_init(CURL_GLOBAL_ALL);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "file",
CURLFORM_FILE, "/path/to/audio.mp3",
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "model",
CURLFORM_COPYCONTENTS, "whisper-1",
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "language",
CURLFORM_COPYCONTENTS, "en",
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "response_format",
CURLFORM_COPYCONTENTS, "json",
CURLFORM_END);
curl = curl_easy_init();
headers = curl_slist_append(headers, "Authorization: Bearer ");
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://api.apimart.ai/v1/audio/transcriptions");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headers);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/audio/transcriptions"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
NSString *boundary = @"Boundary-12345";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];
NSMutableData *body = [NSMutableData data];
// Add file
NSData *fileData = [NSData dataWithContentsOfFile:@"/path/to/audio.mp3"];
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"audio.mp3\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: audio/mpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:fileData];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// Add other fields
NSDictionary *fields = @{@"model": @"whisper-1", @"language": @"en", @"response_format": @"json"};
for (NSString *key in fields) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", fields[key]] dataUsingEncoding:NSUTF8StringEncoding]];
}
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/audio/transcriptions"
(* Note: Multipart form data handling in OCaml requires additional libraries *)
let () =
print_endline "Use multipart_form library to handle file uploads"
```
```dart Dart theme={null}
import 'dart:io';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/audio/transcriptions');
var request = http.MultipartRequest('POST', url);
request.headers['Authorization'] = 'Bearer ';
request.files.add(await http.MultipartFile.fromPath('file', '/path/to/audio.mp3'));
request.fields['model'] = 'whisper-1';
request.fields['language'] = 'en';
request.fields['response_format'] = 'json';
var response = await request.send();
var responseData = await response.stream.bytesToString();
print(responseData);
}
```
```r R theme={null}
library(httr)
url <- "https://api.apimart.ai/v1/audio/transcriptions"
response <- POST(
url,
add_headers(Authorization = "Bearer "),
body = list(
file = upload_file("/path/to/audio.mp3"),
model = "whisper-1",
language = "en",
response_format = "json"
),
encode = "multipart"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"text": "This is a transcribed text from the test audio."
}
```
```json 200 (Verbose Format) theme={null}
{
"task": "transcribe",
"language": "en",
"duration": 8.5,
"text": "This is a transcribed text from the test audio.",
"segments": [
{
"id": 0,
"seek": 0,
"start": 0.0,
"end": 3.5,
"text": "This is a transcribed text",
"tokens": [50364, 1234, 5678],
"temperature": 0.0,
"avg_logprob": -0.3,
"compression_ratio": 1.2,
"no_speech_prob": 0.01
}
]
}
```
```srt 200 (SRT Subtitle Format) theme={null}
1
00:00:00,000 --> 00:00:03,500
This is a transcribed text
2
00:00:03,500 --> 00:00:08,500
from the test audio.
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please recharge",
"type": "payment_required"
}
}
```
```json 413 theme={null}
{
"error": {
"code": 413,
"message": "File size exceeds limit (maximum 25MB)",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway, server temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All interfaces require Bearer Token authentication
Get API Key:
Visit [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
**⚠️ Online testing (Try it) is not supported for this endpoint**
Due to file upload limitations, please test using:
* **Apifox / Postman** - Manually change `file` parameter to file type after importing
* **cURL** - Refer to code examples on the right
* **SDK** - Use SDK examples in various languages
Audio file to transcribe (File type)
**⚠️ Note**: When testing with Apifox or similar tools:
1. After importing, manually change this parameter type to `file`
2. Ensure request Content-Type is `multipart/form-data`
Supported formats: mp3, mp4, mpeg, mpga, m4a, wav, webm
Maximum file size: 25 MB
Speech recognition model name
Example: `"whisper-1"`
Language code of the audio (ISO-639-1 format)
Specifying the language can improve accuracy and speed
Supported languages include: zh (Chinese), en (English), ja (Japanese), ko (Korean), and 99 other languages
Example: `"en"`
Optional text prompt to guide the transcription style or continue from previous audio
Maximum 224 tokens
Output format
Supported formats:
* `json` - JSON format (text only)
* `text` - Plain text
* `srt` - SRT subtitle format
* `verbose_json` - Verbose JSON format (includes timestamps and metadata)
* `vtt` - WebVTT subtitle format
Sampling temperature, range 0 to 1
Higher values (like 0.8) make output more random, lower values (like 0.2) make it more deterministic and consistent
## Response
Transcribed text content
Task type, fixed as `transcribe`
Only returned in verbose\_json format
Detected or specified language code
Only returned in verbose\_json format
Audio duration (seconds)
Only returned in verbose\_json format
Array of text segments
Only returned in verbose\_json format
Segment ID
Segment start time (seconds)
Segment end time (seconds)
Segment text content
Sampling temperature used
Average log probability
Compression ratio
No speech probability
# FLUX.2 Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/flux-2/generation
POST https://api.apimart.ai/v1/images/generations
Submit asynchronous FLUX.2 text-to-image or reference-image generation tasks. The API returns a task ID; poll the task endpoint for the generated image.
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flux-2-pro",
"prompt": "A blue cat sitting on the grass",
"resolution": "2MP",
"size": "16:9",
"output_format": "jpeg"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "flux-2-pro",
"prompt": "A blue cat sitting on the grass",
"resolution": "2MP",
"size": "16:9",
"output_format": "jpeg"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "flux-2-pro",
prompt: "A blue cat sitting on the grass",
resolution: "2MP",
size: "16:9",
output_format: "jpeg"
};
const response = await fetch(url, {
method: "POST",
headers: {
"Authorization": "Bearer ",
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
});
console.log(await response.json());
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KFG5BBFNK1YQDTJDZY0P0QT2"
}
]
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance, please top up",
"type": "payment_required"
}
}
```
## Supported Models
| Model | Description |
| ------------- | -------------------------------------------------------------------- |
| `flux-2-flex` | Fine-grained generation with adjustable sampling steps and guidance. |
| `flux-2-pro` | Balanced quality and speed for general-purpose production workflows. |
| `flux-2-max` | Highest-quality FLUX.2 model for maximum detail. |
All three models support text-to-image generation and reference-image generation.
## Authorizations
All endpoints require Bearer Token authentication.
Get an API key from [API Key Management](https://apimart.ai/keys), then add it to the request header:
```text theme={null}
Authorization: Bearer YOUR_API_KEY
```
## Body
Model name:
* `flux-2-flex`
* `flux-2-pro`
* `flux-2-max`
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description of the image to generate or the edit to apply to the reference images.
Output resolution preset. Supported values:
* `1MP`
* `2MP` (default)
* `3MP`
* `4MP`
Here, `1MP` equals 1,048,576 pixels.
Legacy aliases remain accepted: `512` / `512P` / `1M` map to `1MP`, `1K` / `1024` map to `2MP`, `2K` / `2048` map to `3MP`, and `4K` maps to `4MP`. Any other value causes the task to fail.
The preset determines the output dimensions when `size` is an aspect ratio.
Output aspect ratio or pixel dimensions.
`size` also supports `auto`: when `image_urls` is provided, the output follows the reference image aspect ratio while keeping the current `resolution` tier; without a reference image, it uses the default `1:1`.
Supported size options:
* `1:1` (default)
* `4:3`
* `3:4`
* `16:9`
* `9:16`
* `3:2`
* `2:3`
* `21:9`
* `9:21`
* `auto` - Follow the reference image aspect ratio
You may also provide a pixel string such as `1024x1536`. Exact pixel dimensions are subject to the same pixel limits as `width` and `height` and take priority over `resolution` and an aspect ratio.
Exact output width in pixels. It must be provided together with `height`, and each dimension must be at least 64 pixels. Supplying only one dimension causes the task to fail.
A complete `width` and `height` pair has the highest priority and overrides `resolution` and `size`.
Exact output height in pixels. It must be provided together with `width`, and each dimension must be at least 64 pixels. Supplying only one dimension causes the task to fail.
The output must not exceed 4 MP (`width × height ≤ 4,194,304`), and the output plus all reference images must not exceed 9 MP in total.
Reference images for image-to-image generation. Publicly accessible image URLs and Base64 input are supported.
* Maximum: 8 images
* The output plus all reference images must not exceed 9 MP in total
Output image encoding. Supported values: `jpeg`, `png`, and `webp`.
Number of images generated per task. The only supported value is `1`; submit multiple tasks concurrently if you need multiple images.
Random seed. Reuse the same seed and parameters for reproducible output; omit it to use a random seed.
Whether to enhance and rewrite the prompt before generation. The default is `false`. Pass `false` explicitly to disable prompt rewriting.
Safety tolerance from `0` to `5`. Higher values are more permissive.
Sampling steps from `1` to `50`. Higher values can improve detail but take longer.
This parameter is supported only by `flux-2-flex`. Do not send it with `flux-2-pro` or `flux-2-max`.
Prompt guidance from `1.5` to `10`. Higher values follow the prompt more closely.
This parameter is supported only by `flux-2-flex`. Do not send it with `flux-2-pro` or `flux-2-max`.
## Resolution Reference Table
| Aspect ratio | `1MP` | `2MP` (default) | `3MP` | `4MP` |
| ------------ | --------: | --------------: | --------: | --------: |
| `1:1` | 1024×1024 | 1440×1440 | 1536×1536 | 2048×2048 |
| `4:3` | 1152×864 | 1664×1248 | 1824×1360 | 2336×1760 |
| `3:4` | 864×1152 | 1248×1664 | 1360×1824 | 1760×2336 |
| `16:9` | 1344×752 | 1920×1072 | 2048×1152 | 2720×1536 |
| `9:16` | 752×1344 | 1072×1920 | 1152×2048 | 1536×2720 |
| `3:2` | 1248×832 | 1728×1152 | 1872×1248 | 2496×1664 |
| `2:3` | 832×1248 | 1152×1728 | 1248×1872 | 1664×2496 |
| `21:9` | 1504×640 | 2176×928 | 2304×992 | 3072×1312 |
| `9:21` | 640×1504 | 928×2176 | 992×2304 | 1312×3072 |
Dimension priority is: paired `width` + `height` → a pixel-string `size` → `resolution` + aspect-ratio `size` → the default `2MP` + `1:1`.
## Usage Examples
### Text-to-image
```json theme={null}
{
"model": "flux-2-pro",
"prompt": "A cinematic city at night with neon reflections on wet streets",
"resolution": "1MP",
"size": "16:9"
}
```
### Reference-image generation
```json theme={null}
{
"model": "flux-2-pro",
"prompt": "Place the person from the first image in the scene from the second image and match the lighting",
"image_urls": [
"https://example.com/person.jpg",
"https://example.com/scene.jpg"
],
"resolution": "2MP",
"output_format": "webp"
}
```
### Exact output dimensions
```json theme={null}
{
"model": "flux-2-max",
"prompt": "A highly detailed botanical illustration",
"width": 1024,
"height": 1536
}
```
### FLUX.2 Flex controls
```json theme={null}
{
"model": "flux-2-flex",
"prompt": "A minimalist poster with the headline SUMMER SALE and the subheading 50% OFF",
"resolution": "3MP",
"size": "3:4",
"steps": 50,
"guidance": 6.5
}
```
## Response
Response status code.
Submission result array.
Submission status. A successfully accepted task returns `submitted`.
Unique task identifier. Use it to poll the task endpoint.
## Retrieve the Result
Poll `GET /v1/tasks/{task_id}` until the task reaches `completed` or `failed`. See the [Task Status API](/en/api-reference/tasks/status) for the complete response schema.
Task statuses:
| Status | Meaning |
| ----------------------- | ------------------------------------------------------------------------- |
| `submitted` / `pending` | Accepted or queued; continue polling. |
| `processing` | Image generation is in progress; continue polling. |
| `completed` | Generation succeeded; the image is available in `result.images`. |
| `failed` | Generation failed; read `data.error.message`. The task is fully refunded. |
A completed task includes one generated image:
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KFG5BBFNK1YQDTJDZY0P0QT2",
"status": "completed",
"progress": 100,
"result": {
"images": [
{
"url": ["https://upload.apimart.ai/f/image/xxxxxxxx-flux-2.jpeg"],
"expires_at": 1785220083
}
]
}
}
}
```
The image URL is `data.result.images[0].url[0]`. Its expiration is defined by the Unix timestamp in `data.result.images[0].expires_at`; download the image before that time.
### Invalid parameters and failed tasks
Invalid model parameters do not produce a synchronous 4xx response. The submission still returns HTTP 200 with a `task_id`; keep polling until the task becomes `failed`, then read the specific reason from `data.error.message`. Failed tasks are fully refunded.
```json theme={null}
{
"code": 200,
"data": {
"status": "failed",
"error": {
"type": "task_failed",
"code": "task_failed",
"message": "`steps` must be between 1 and 50 (got 0)"
}
}
}
```
`error.code` is always `task_failed`; the specific reason is in `error.message`.
## Notes
1. Tasks are processed asynchronously. The submission response returns a `task_id` for polling.
2. `n` defaults to `1`, which is the only supported value.
3. Reference images may use publicly accessible image URLs or Base64 input.
4. Up to 8 reference images are supported, subject to the 9 MP combined input-and-output limit.
5. Exact output dimensions can be set with a pixel-string `size`, or with paired `width` and `height`. When used, both dimensions must be at least 64 pixels; output is limited to 4 MP.
6. Result URL expiration is determined by the `expires_at` value returned in the task response.
7. Invalid model parameters are returned asynchronously: poll until `failed` and read `data.error.message`.
# FLUX Kontext Image Generation and Editing
Source: https://docs.apimart.ai/en/api-reference/images/flux-kontext/generation
POST https://api.apimart.ai/v1/images/generations
Submit asynchronous FLUX Kontext image generation or image editing tasks. The API returns a task ID; poll the task endpoint for the generated image.
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flux-kontext-pro",
"prompt": "Change the hair color to blue",
"image_urls": ["https://example.com/portrait.jpg"],
"size": "1:1",
"output_format": "png"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "flux-kontext-pro",
"prompt": "Change the hair color to blue",
"image_urls": ["https://example.com/portrait.jpg"],
"size": "1:1",
"output_format": "png"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "flux-kontext-pro",
prompt: "Change the hair color to blue",
image_urls: ["https://example.com/portrait.jpg"],
size: "1:1",
output_format: "png"
};
const response = await fetch(url, {
method: "POST",
headers: {
"Authorization": "Bearer ",
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
});
console.log(await response.json());
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KFG5BBFNK1YQDTJDZY0P0QT2"
}
]
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance, please top up",
"type": "payment_required"
}
}
```
## Supported Models
| Model | Description |
| ------------------ | ------------------------------------------------------------------------- |
| `flux-kontext-pro` | Context-aware image generation and editing for general-purpose workflows. |
| `flux-kontext-max` | Higher-quality context-aware image generation and editing. |
Both models support text-to-image generation without reference images and image editing with reference images.
## Authorizations
All endpoints require Bearer Token authentication.
Get an API key from [API Key Management](https://apimart.ai/keys), then add it to the request header:
```text theme={null}
Authorization: Bearer YOUR_API_KEY
```
## Body
Model name:
* `flux-kontext-pro`
* `flux-kontext-max`
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description of the image to generate or the edit to apply to the reference images.
Reference images for image editing. Publicly accessible image URLs and Base64 input are supported.
* Maximum: 4 images
* The output plus all reference images must not exceed 9 MP in total
If a reference URL cannot be accessed publicly, the task may return only `temporarily unavailable dependency`. When this happens, first check hotlink protection, access permissions, and expired signatures.
Output aspect ratio. A pixel string such as `1024x1536` is also accepted, but Kontext maps it to the closest supported ratio rather than producing those exact pixel dimensions. Supported aspect ratios and automatic mode:
* `1:1` (default)
* `4:3`
* `3:4`
* `16:9`
* `9:16`
* `3:2`
* `2:3`
* `21:9`
* `9:21`
* `auto` - Follow the reference image aspect ratio
When `size` is set to `auto`, the output follows the reference image's aspect ratio if `image_urls` is provided. Without a reference image, it uses the default `1:1` ratio.
Kontext does not support `width` or `height`; supplying either field causes the task to fail. Use `size` to control the aspect ratio. `resolution` has no effect for Kontext, whose output remains approximately 1 MP.
Output image encoding. Supported values: `png`, `jpeg`, and `webp`.
OpenAI-compatible response-shape field. It accepts only `url` or `b64_json` and does not change the image encoding. When both fields are supplied, `output_format` takes priority.
Number of images generated per task. The only supported value is `1`; submit multiple tasks concurrently if you need multiple images.
Random seed. Reuse the same seed and parameters for reproducible output; omit it to use a random seed.
Whether to enhance and rewrite the prompt before generation.
Set this parameter explicitly to `false` to disable prompt rewriting.
Safety tolerance from `0` to `6`. Higher values are more permissive.
## Supported Aspect Ratios
| Aspect ratio | Orientation |
| ------------ | -------------------- |
| `1:1` | Square (default) |
| `4:3` | Landscape |
| `3:4` | Portrait |
| `16:9` | Widescreen landscape |
| `9:16` | Vertical portrait |
| `3:2` | Classic landscape |
| `2:3` | Classic portrait |
| `21:9` | Ultra-wide landscape |
| `9:21` | Ultra-tall portrait |
### Actual Output Dimensions
| Ratio | Actual output dimensions |
| ------ | ------------------------ |
| `1:1` | 1024×1024 |
| `4:3` | 1184×880 |
| `3:4` | 880×1184 |
| `16:9` | 1392×752 |
| `9:16` | 752×1392 |
| `3:2` | 1248×832 |
| `2:3` | 832×1248 |
| `21:9` | 1568×672 |
| `9:21` | 672×1568 |
## Usage Examples
### Text-to-image generation
```json theme={null}
{
"model": "flux-kontext-pro",
"prompt": "A cozy reading nook with warm lamplight",
"size": "4:3"
}
```
### Image editing
```json theme={null}
{
"model": "flux-kontext-max",
"prompt": "Replace the background with a beach while preserving the person",
"image_urls": ["https://example.com/portrait.jpg"],
"size": "16:9",
"output_format": "webp"
}
```
### Multiple reference images
```json theme={null}
{
"model": "flux-kontext-pro",
"prompt": "Place the product from the first image into the room from the second image",
"image_urls": [
"https://example.com/product.jpg",
"https://example.com/room.jpg"
],
"size": "4:3"
}
```
## Response
Response status code.
Submission result array.
Submission status. A successfully accepted task returns `submitted`.
Unique task identifier. Use it to poll the task endpoint.
## Retrieve the Result
Poll `GET /v1/tasks/{task_id}` until the task reaches `completed` or `failed`. See the [Task Status API](/en/api-reference/tasks/status) for the complete response schema.
Task statuses:
| Status | Meaning |
| ----------------------- | ------------------------------------------------------------------------- |
| `submitted` / `pending` | Accepted or queued; continue polling. |
| `processing` | Image generation is in progress; continue polling. |
| `completed` | Generation succeeded; the image is available in `result.images`. |
| `failed` | Generation failed; read `data.error.message`. The task is fully refunded. |
A completed task includes one generated image:
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KFG5BBFNK1YQDTJDZY0P0QT2",
"status": "completed",
"progress": 100,
"result": {
"images": [
{
"url": ["https://upload.apimart.ai/f/image/xxxxxxxx-flux-kontext.png"],
"expires_at": 1785220083
}
]
}
}
}
```
The image URL is `data.result.images[0].url[0]`. Its expiration is defined by the Unix timestamp in `data.result.images[0].expires_at`; download the image before that time.
### Invalid parameters and failed tasks
Invalid model parameters do not produce a synchronous 4xx response. The submission still returns HTTP 200 with a `task_id`; keep polling until the task becomes `failed`, then read the specific reason from `data.error.message`. Failed tasks are fully refunded.
```json theme={null}
{
"code": 200,
"data": {
"status": "failed",
"error": {
"type": "task_failed",
"code": "task_failed",
"message": "width/height are not supported by flux-kontext-pro"
}
}
}
```
`error.code` is always `task_failed`; the specific reason is in `error.message`.
## Notes
1. Tasks are processed asynchronously. The submission response returns a `task_id` for polling.
2. `n` defaults to `1`, which is the only supported value.
3. Reference images may use publicly accessible image URLs or Base64 input.
4. Up to 4 reference images are supported, subject to the 9 MP combined input-and-output limit.
5. Set `prompt_upsampling: false` explicitly to disable prompt rewriting.
6. Result URL expiration is determined by the `expires_at` value returned in the task response.
7. `width` and `height` cause the task to fail; `resolution` does not change the approximately 1 MP output; a pixel-string `size` maps to the closest supported ratio.
8. Invalid model parameters are returned asynchronously: poll until `failed` and read `data.error.message`.
# Nano banana Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/gemini-2.5-flash/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Fast generation speed, optimized for quick image creation
- Generated image links are valid for 24 hours, please save them promptly
**Model name compatibility note**: This endpoint also accepts the alias `nano-banana-ext`, which is equivalent to `gemini-2.5-flash-image-preview`. The two are interchangeable and produce identical results.
```bash cURL theme={null}
# model can be "gemini-2.5-flash-image-preview", or the compatible alias "nano-banana-ext"
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gemini-2.5-flash-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"image_urls": [
"https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "gemini-2.5-flash-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"image_urls": [
"https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "gemini-2.5-flash-image-preview",
prompt: "A bamboo forest path under moonlight",
size: "1:1",
n: 1,
image_urls: [
"https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "gemini-2.5-flash-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"image_urls": []string{
"https://openai-documentation.vercel.app/images/cat_and_otter.png",
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "gemini-2.5-flash-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"image_urls": [
"https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"gemini-2.5-flash-image-preview",
"prompt" => "A bamboo forest path under moonlight",
"size" => "1:1",
"n" => 1,
"image_urls" => [
"https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "gemini-2.5-flash-image-preview",
prompt: "A bamboo forest path under moonlight",
size: "1:1",
n: 1,
image_urls: [
"https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "gemini-2.5-flash-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"image_urls": [
"https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""gemini-2.5-flash-image-preview"",
""prompt"": ""A bamboo forest path under moonlight"",
""size"": ""1:1"",
""n"": 1,
""image_urls"": [
""https://openai-documentation.vercel.app/images/cat_and_otter.png""
]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/images/generations";
const char *payload = "{"
"\"model\":\"gemini-2.5-flash-image-preview\","
"\"prompt\":\"A bamboo forest path under moonlight\","
"\"size\":\"1:1\","
"\"n\":1,"
"\"image_urls\":[\"https://openai-documentation.vercel.app/images/cat_and_otter.png\"]"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/images/generations"];
NSDictionary *payload = @{
@"model": @"gemini-2.5-flash-image-preview",
@"prompt": @"A bamboo forest path under moonlight",
@"size": @"1:1",
@"n": @1,
@"image_urls": @[
@"https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/images/generations"
let payload = {|{
"model": "gemini-2.5-flash-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"image_urls": [
"https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'gemini-2.5-flash-image-preview',
'prompt': 'A bamboo forest path under moonlight',
'size': '1:1',
'n': 1,
'image_urls': [
'https://openai-documentation.vercel.app/images/cat_and_otter.png'
]
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "gemini-2.5-flash-image-preview",
prompt = "A bamboo forest path under moonlight",
size = "1:1",
n = 1,
image_urls = list(
"https://openai-documentation.vercel.app/images/cat_and_otter.png"
)
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
Supported models:
* `gemini-2.5-flash-image-preview` - Standard version (compatible alias `nano-banana-ext`)
* `gemini-2.5-flash-image-preview-official` - Official version (compatible alias `nano-banana`)
Example: `"gemini-2.5-flash-image-preview"` or `"gemini-2.5-flash-image-preview-official"`
For backward compatibility, the aliases `nano-banana-ext` (for `gemini-2.5-flash-image-preview`) and `nano-banana` (for `gemini-2.5-flash-image-preview-official`) remain usable.
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
Maximum 1000 characters
Image generation size
Supported formats:
* Ratio: `auto`, `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `4:5`, `5:4`, `9:16`, `16:9`, `21:9`
For text-to-image, when `size` is `auto`, the default is `1:1` or `16:9`; for image-to-image, the aspect ratio follows the upstream response. We recommend specifying an aspect ratio.
Output image resolution
Supported values:
* `1K` - 1K resolution (default)
Number of images to generate
Range: 1
Default: 1
**⚠️ Note:** Must enter a plain number (e.g., `1`), do not use quotes or it will cause an error
Whether to use the official channel fallback
* `false`: Do not use (default)
* `true`: Use official channel
When using the official channel (`gemini-2.5-flash-image-preview-official`), this parameter cannot be used.
List of reference image URLs for image-to-image or image editing
**💡 Quick Fill (Try it area):**
1. Click "+ Add an item" to add an image URL
2. Enter the complete image URL address or base64 data
Each element in the array is a string, supporting two formats:
**1. Complete image URL address**
* Publicly accessible image URL (http\:// or https\://)
* Example: `"https://example.com/image.jpg"`
**2. Base64 encoded format**
* **Must use complete Data URI format**
* Format: `data:image/{format};base64,{base64data}`
* Supported image formats: jpeg, png, webp, etc.
* Example: `"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg..."`
* ⚠️ Note: Must include the `data:image/jpeg;base64,` prefix
**Limitations:**
* Single image must not exceed 10MB
* Supported formats: .jpeg, .jpg, .png, .webp
**Limit:** Maximum 14 images
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
# Nano banana Pro Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/gemini-3-pro/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- High-quality image generation, professional-grade image creation
- Generated image links are valid for 24 hours, please save them promptly
**Model name compatibility note**: This endpoint also accepts the alias `nano-banana-pro-ext`, which is equivalent to `gemini-3-pro-image-preview`. The two are interchangeable and produce identical results.
```bash cURL theme={null}
# model can be "gemini-3-pro-image-preview", or the compatible alias "nano-banana-pro-ext"
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gemini-3-pro-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"resolution": "1K"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "gemini-3-pro-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"resolution": "1K"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "gemini-3-pro-image-preview",
prompt: "A bamboo forest path under moonlight",
size: "1:1",
n: 1,
resolution: "2K"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "gemini-3-pro-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"resolution": "1K",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "gemini-3-pro-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"resolution": "1K"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"gemini-3-pro-image-preview",
"prompt" => "A bamboo forest path under moonlight",
"size" => "1:1",
"n" => 1,
"resolution" => "2K"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "gemini-3-pro-image-preview",
prompt: "A bamboo forest path under moonlight",
size: "1:1",
n: 1,
resolution: "2K"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "gemini-3-pro-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"resolution": "1K"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""gemini-3-pro-image-preview"",
""prompt"": ""A bamboo forest path under moonlight"",
""size"": ""1:1"",
""n"": 1,
""resolution"": ""2K""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/images/generations";
const char *payload = "{"
"\"model\":\"gemini-3-pro-image-preview\","
"\"prompt\":\"A bamboo forest path under moonlight\","
"\"size\":\"1:1\","
"\"n\":1,"
"\"resolution\":\"2K\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/images/generations"];
NSDictionary *payload = @{
@"model": @"gemini-3-pro-image-preview",
@"prompt": @"A bamboo forest path under moonlight",
@"size": @"1:1",
@"n": @1,
@"resolution": @"2K"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/images/generations"
let payload = {|{
"model": "gemini-3-pro-image-preview",
"prompt": "A bamboo forest path under moonlight",
"size": "1:1",
"n": 1,
"resolution": "1K"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'gemini-3-pro-image-preview',
'prompt': 'A bamboo forest path under moonlight',
'size': '1:1',
'n': 1,
'resolution': '1K'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json'
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "gemini-3-pro-image-preview",
prompt = "A bamboo forest path under moonlight",
size = "1:1",
n = 1,
resolution = "1K"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please recharge",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, server temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All APIs require authentication using Bearer Token
Get API Key:
Visit [API Key Management Page](https://apimart.ai/keys) to obtain your API Key
Add to request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
Supported models:
* `gemini-3-pro-image-preview` - Standard version (compatible alias `nano-banana-pro-ext`)
* `gemini-3-pro-image-preview-official` - Official version (compatible alias `nano-banana-pro`)
Example: `"gemini-3-pro-image-preview"` or `"gemini-3-pro-image-preview-official"`
For backward compatibility, the aliases `nano-banana-pro-ext` (for `gemini-3-pro-image-preview`) and `nano-banana-pro` (for `gemini-3-pro-image-preview-official`) remain usable.
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
Image generation size
Supported formats:
* Ratios: `auto`, `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `4:5`, `5:4`, `9:16`, `16:9`, `21:9`
For text-to-image, when `size` is `auto`, the default is `1:1` or `16:9`; for image-to-image, the aspect ratio follows the upstream response. We recommend specifying an aspect ratio.
Number of images to generate
Range: 1
Default: 1
**⚠️ Note:** Must be a pure number (e.g. `1`), do not add quotes, otherwise it will error
Output image resolution
Supported values:
* `1K` - 1K resolution (default)
* `2K` - 2K resolution
* `4K` - 4K resolution
**⚠️ Note:** Generating 4K images with base64 format takes longer processing time
Whether to use the official channel fallback
* `false`: Do not use (default)
* `true`: Use official channel
When using the official channel (`gemini-3-pro-image-preview-official`), this parameter cannot be used.
List of reference image URLs for image-to-image or image editing
**💡 Quick Fill (Try it area):**
1. Click "+ Add an item" to add an image URL
2. Enter the complete image URL address or base64 data
Each element in the array is a string, supporting two formats:
**1. Complete image URL address**
* Publicly accessible image URL (http\:// or https\://)
* Example: `"https://example.com/image.jpg"`
**2. Base64 encoded format**
* **Must use complete Data URI format**
* Format: `data:image/{format};base64,{base64data}`
* Supported image formats: jpeg, png, webp, etc.
* Example: `"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg..."`
* ⚠️ Note: Must include the `data:image/jpeg;base64,` prefix
**Limitations:**
* Single image must not exceed 30MB
* Supported formats: .jpeg, .jpg, .png, .webp
**Limit:** Maximum 14 images
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
# Nano banana2 Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/gemini-3.1-flash/generation
POST https://api.apimart.ai/v1/images/generations
- Supports text-to-image and image-to-image, up to 4K resolution output
- Up to 14 reference images for style/character consistency
- Supports extreme aspect ratios (1:4, 4:1, 1:8, 8:1)
- Integrated Google Search enhancement for more realistic image generation
**Model name compatibility note**: This endpoint also accepts the alias `nano-banana-2-ext`, which is equivalent to `gemini-3.1-flash-image-preview`. The two are interchangeable and produce identical results.
```bash cURL theme={null}
# model can be "gemini-3.1-flash-image-preview", or the compatible alias "nano-banana-2-ext"
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gemini-3.1-flash-image-preview",
"prompt": "Cyberpunk cityscape at night with neon lights",
"size": "16:9",
"resolution": "2K",
"n": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "gemini-3.1-flash-image-preview",
"prompt": "Cyberpunk cityscape at night with neon lights",
"size": "16:9",
"resolution": "2K",
"n": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "gemini-3.1-flash-image-preview",
prompt: "Cyberpunk cityscape at night with neon lights",
size: "16:9",
resolution: "2K",
n: 1
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "gemini-3.1-flash-image-preview",
"prompt": "Cyberpunk cityscape at night with neon lights",
"size": "16:9",
"resolution": "2K",
"n": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "gemini-3.1-flash-image-preview",
"prompt": "Cyberpunk cityscape at night with neon lights",
"size": "16:9",
"resolution": "2K",
"n": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"gemini-3.1-flash-image-preview",
"prompt" => "Cyberpunk cityscape at night with neon lights",
"size" => "16:9",
"resolution" => "2K",
"n" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "gemini-3.1-flash-image-preview",
prompt: "Cyberpunk cityscape at night with neon lights",
size: "16:9",
resolution: "2K",
n: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "gemini-3.1-flash-image-preview",
"prompt": "Cyberpunk cityscape at night with neon lights",
"size": "16:9",
"resolution": "2K",
"n": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""gemini-3.1-flash-image-preview"",
""prompt"": ""Cyberpunk cityscape at night with neon lights"",
""size"": ""16:9"",
""resolution"": ""2K"",
""n"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/images/generations";
const char *payload = "{"
"\"model\":\"gemini-3.1-flash-image-preview\","
"\"prompt\":\"Cyberpunk cityscape at night with neon lights\","
"\"size\":\"16:9\","
"\"resolution\":\"2K\","
"\"n\":1"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/images/generations"];
NSDictionary *payload = @{
@"model": @"gemini-3.1-flash-image-preview",
@"prompt": @"Cyberpunk cityscape at night with neon lights",
@"size": @"16:9",
@"resolution": @"2K",
@"n": @1
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/images/generations"
let payload = {|{
"model": "gemini-3.1-flash-image-preview",
"prompt": "Cyberpunk cityscape at night with neon lights",
"size": "16:9",
"resolution": "2K",
"n": 1
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'gemini-3.1-flash-image-preview',
'prompt': 'Cyberpunk cityscape at night with neon lights',
'size': '16:9',
'resolution': '2K',
'n': 1
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "gemini-3.1-flash-image-preview",
prompt = "Cyberpunk cityscape at night with neon lights",
size = "16:9",
resolution = "2K",
n = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
Supported models:
* `gemini-3.1-flash-image-preview` - Standard version (compatible alias `nano-banana-2-ext`)
* `gemini-3.1-flash-image-preview-official` - Official version (compatible alias `nano-banana-2`)
Example: `"gemini-3.1-flash-image-preview"` or `"gemini-3.1-flash-image-preview-official"`
For backward compatibility, the aliases `nano-banana-2-ext` (for `gemini-3.1-flash-image-preview`) and `nano-banana-2` (for `gemini-3.1-flash-image-preview-official`) remain usable.
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
Image aspect ratio
Supported ratios:
* `auto` - Automatically choose the aspect ratio
* `1:1` - Square, avatars, social media
* `3:2` / `2:3` - Standard photos
* `4:3` / `3:4` - Traditional display ratio
* `16:9` / `9:16` - Widescreen / vertical video covers
* `5:4` / `4:5` - Instagram images
* `21:9` - Ultra-wide banner
* `1:4` / `4:1` - Long poster / banner
* `1:8` / `8:1` - Extreme long images / banner ads
For text-to-image, when `size` is `auto`, the default is `1:1` or `16:9`; for image-to-image, the aspect ratio follows the upstream response. We recommend specifying an aspect ratio.
Output image resolution
Supported values:
* `0.5K` - \~512px, low-resolution preview
* `1K` - \~1024px, standard resolution (default)
* `2K` - \~2048px, high resolution
* `4K` - \~4096px, ultra-high resolution
> **Note:** Different resolutions have different pricing. 4K costs more than 1K.
Number of images to generate
Range: 1
Default: 1
**⚠️ Note:** Must enter a plain number (e.g., `1`), do not use quotes or it will cause an error
Whether to use the official channel fallback
* `false`: Do not use (default)
* `true`: Use official channel
When using the official channel (`gemini-3.1-flash-image-preview-official`), this parameter cannot be used.
Reference image URL list for image-to-image generation
Two formats are supported:
**1. Full image URL**
* Publicly accessible image URL (http\:// or https\://)
* Example: `https://example.com/image.jpg`
**2. Base64 encoded format**
* **Must use the full Data URI format**
* Format: `data:image/{format};base64,{base64data}`
* Supported image formats: jpeg, png, webp
* Example: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg...`
* ⚠️ Note: Must include the `data:image/jpeg;base64,` prefix
**Limitations:**
* Maximum **14** reference images (recommended: up to 10 object refs + 4 character refs)
* Single image size: not exceeding 10MB
* Supported formats: jpeg, png, webp
Enable Google text search enhancement
* `true`: The model will search web text information to assist image generation, suitable for scenarios requiring real-world information
* `false`: Disabled (default)
Enable Google image search enhancement
* `true`: In addition to text search, will also search for reference images to assist generation, suitable for scenarios requiring visual references
* `false`: Disabled (default)
> **Note:** Must be used together with `google_search: true`
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
# Nano Banana Lite Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/gemini-3.1-flash/generation-lite
POST https://api.apimart.ai/v1/images/generations
- The fastest and cheapest image model in the Gemini 3.1 family, designed for large-scale, low-cost image generation
- Supports 1K resolution only (passing 2K/4K/0.5K is automatically downgraded to 1K without an error)
- Supports text-to-image and image-to-image, up to 14 reference images
- Billed by input / output tokens; connects directly to the official Gemini channel, with asynchronous task-based image generation
**Model-name compatibility note**: `gemini-3.1-flash-lite-image` also accepts the alias `nano-banana-2-lite`, and `gemini-3.1-flash-lite-image-ext` also accepts the alias `nano-banana-2-lite-ext`; each name and its alias are equivalent and interchangeable.
```bash cURL theme={null}
# model can be "gemini-3.1-flash-lite-image", the alias "nano-banana-2-lite" also works
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gemini-3.1-flash-lite-image",
"prompt": "赛博朋克风格的城市夜景,霓虹灯闪烁",
"size": "16:9",
"resolution": "1K",
"n": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "gemini-3.1-flash-lite-image",
"prompt": "赛博朋克风格的城市夜景,霓虹灯闪烁",
"size": "16:9",
"resolution": "1K",
"n": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "gemini-3.1-flash-lite-image",
prompt: "赛博朋克风格的城市夜景,霓虹灯闪烁",
size: "16:9",
resolution: "1K",
n: 1
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "gemini-3.1-flash-lite-image",
"prompt": "赛博朋克风格的城市夜景,霓虹灯闪烁",
"size": "16:9",
"resolution": "1K",
"n": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "gemini-3.1-flash-lite-image",
"prompt": "赛博朋克风格的城市夜景,霓虹灯闪烁",
"size": "16:9",
"resolution": "1K",
"n": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"gemini-3.1-flash-lite-image",
"prompt" => "赛博朋克风格的城市夜景,霓虹灯闪烁",
"size" => "16:9",
"resolution" => "1K",
"n" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "gemini-3.1-flash-lite-image",
prompt: "赛博朋克风格的城市夜景,霓虹灯闪烁",
size: "16:9",
resolution: "1K",
n: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "gemini-3.1-flash-lite-image",
"prompt": "赛博朋克风格的城市夜景,霓虹灯闪烁",
"size": "16:9",
"resolution": "1K",
"n": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""gemini-3.1-flash-lite-image"",
""prompt"": ""赛博朋克风格的城市夜景,霓虹灯闪烁"",
""size"": ""16:9"",
""resolution"": ""1K"",
""n"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/images/generations";
const char *payload = "{"
"\"model\":\"gemini-3.1-flash-lite-image\","
"\"prompt\":\"赛博朋克风格的城市夜景,霓虹灯闪烁\","
"\"size\":\"16:9\","
"\"resolution\":\"1K\","
"\"n\":1"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/images/generations"];
NSDictionary *payload = @{
@"model": @"gemini-3.1-flash-lite-image",
@"prompt": @"赛博朋克风格的城市夜景,霓虹灯闪烁",
@"size": @"16:9",
@"resolution": @"1K",
@"n": @1
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/images/generations"
let payload = {|{
"model": "gemini-3.1-flash-lite-image",
"prompt": "赛博朋克风格的城市夜景,霓虹灯闪烁",
"size": "16:9",
"resolution": "1K",
"n": 1
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'gemini-3.1-flash-lite-image',
'prompt': '赛博朋克风格的城市夜景,霓虹灯闪烁',
'size': '16:9',
'resolution': '1K',
'n': 1
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "gemini-3.1-flash-lite-image",
prompt = "赛博朋克风格的城市夜景,霓虹灯闪烁",
size = "16:9",
resolution = "1K",
n = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "请求参数无效",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "身份验证失败,请检查您的API密钥",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "账户余额不足,请充值后再试",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "访问被禁止,您没有权限访问此资源",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "请求过于频繁,请稍后再试",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "服务器内部错误,请稍后重试",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "网关错误,服务器暂时不可用",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
The following model names are supported:
* `gemini-3.1-flash-lite-image` (Nano Banana Lite, compatible alias `nano-banana-2-lite`)
* `gemini-3.1-flash-lite-image-ext` (compatible alias `nano-banana-2-lite-ext`)
Both share the same parameters and constraints (1K only, `google_search` / `official_fallback` not supported, up to 14 reference images). Neither has a `-official` variant, and neither supports the `official_fallback` fallback parameter. Billing is subject to the backend configuration of each channel.
The aliases `nano-banana-2-lite` (for `gemini-3.1-flash-lite-image`) and `nano-banana-2-lite-ext` (for `gemini-3.1-flash-lite-image-ext`) are equivalent to their original names and interchangeable.
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
Image aspect ratio
Supported ratios:
* `auto` - Automatically choose the aspect ratio
* `1:1` - Square, avatars, social media
* `3:2` / `2:3` - Standard photos
* `4:3` / `3:4` - Traditional display ratio
* `16:9` / `9:16` - Widescreen / vertical video covers
* `5:4` / `4:5` - Instagram images
* `21:9` - Ultra-wide banner
For text-to-image, when `size` is `auto`, the default is `1:1` or `16:9`; for image-to-image, the aspect ratio follows the upstream response. (We recommend specifying an aspect ratio.)
Output image resolution
Supported values:
* `1K` - \~1024px, standard resolution (**the only tier Lite supports**)
**Lite only supports 1K**. Passing `2K` / `4K` / `0.5K` is **silently downgraded to 1K** — it won't raise an error, nor will it actually output higher resolution. The frontend UI does not need to expose a resolution option.
Number of images to generate
Range: 1 to 4, default `1`
When `n>1`, the backend sends multiple concurrent requests upstream and bills by the **actual number of successful images**. **We recommend the frontend always send 1** (to show progress image by image and make billing more intuitive).
**⚠️ Note:** Must enter a plain number (e.g., `1`), do not use quotes or it will cause an error
Reference image URL list for image-to-image generation
Two formats are supported:
**1. Full image URL**
* Publicly accessible image URL (http\:// or https\://)
* Example: `https://example.com/image.jpg`
**2. Base64 encoded format**
* **Must use the full Data URI format**
* Format: `data:image/{format};base64,{base64data}`
* Supported image formats: jpeg, png, webp
* Example: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg...`
* ⚠️ Note: Must include the `data:image/jpeg;base64,` prefix
**Limitations:**
* Maximum **14** reference images (recommended: up to 10 object refs + 4 character refs)
* Single image size: not exceeding 10MB
* Supported formats: jpeg, png, webp
Task callback URL (base)
When a task succeeds / fails, the platform calls back to `webhook + /callback` (it does not forward the upstream request). Passing this parameter can significantly reduce polling; we still recommend keeping polling as a fallback.
**Lite usage notes**
* **`google_search` / `google_image_search` are not supported**: Lite uses the Developer API's `interactions` endpoint, and the upstream has not enabled the Search tool (it returns "Search as tool is not enabled for this model"), so the platform adapter does not send this parameter either. **Passing it won't raise an error and images are generated as usual, but there is no search enhancement effect at all**. If you need search enhancement, switch to `gemini-3.1-flash-image-preview`.
* `mask_url` inpainting is not supported (the Gemini family uses aspect ratio + reference images rather than masks).
* **Billed by token** (unlike the fixed per-image price of flash/pro): input is about $0.25 per million tokens, image output is about $30 per million tokens, and a single 1K image ≈ 1120 output tokens ≈ **\$0.0336/image**. The actual price is subject to the backend multiplier configuration.
* All generated images contain Google's **SynthID** invisible watermark (upstream behavior, cannot be disabled).
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
# GPT-Image(1/1.5) Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/gpt-image-1/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Supports text-to-image, image-to-image, and inpainting generation modes
- Supports transparent backgrounds, multiple output formats, and quality tiers
- Generate up to 4 images per request, with up to 15 reference images
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gpt-image-1-official",
"prompt": "An ancient castle under a starry sky",
"size": "1:1",
"quality": "auto",
"n": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "gpt-image-1-official",
"prompt": "An ancient castle under a starry sky",
"size": "1:1",
"quality": "auto",
"n": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "gpt-image-1-official",
prompt: "An ancient castle under a starry sky",
size: "1:1",
quality: "auto",
n: 1,
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "gpt-image-1-official",
"prompt": "An ancient castle under a starry sky",
"size": "1:1",
"quality": "auto",
"n": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "gpt-image-1-official",
"prompt": "An ancient castle under a starry sky",
"size": "1:1",
"quality": "auto",
"n": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"gpt-image-1-official",
"prompt" => "An ancient castle under a starry sky",
"size" => "1:1",
"quality" => "auto",
"n" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "gpt-image-1-official",
prompt: "An ancient castle under a starry sky",
size: "1:1",
quality: "auto",
n: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "gpt-image-1-official",
"prompt": "An ancient castle under a starry sky",
"size": "1:1",
"quality": "auto",
"n": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""gpt-image-1-official"",
""prompt"": ""An ancient castle under a starry sky"",
""size"": ""1:1"",
""quality"": ""auto"",
""n"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'gpt-image-1-official',
'prompt': 'An ancient castle under a starry sky',
'size': '1:1',
'quality': 'auto',
'n': 1,
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "gpt-image-1-official",
prompt = "An ancient castle under a starry sky",
size = "1:1",
quality = "auto",
n = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KXXXXXXXXXXXXXXX"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway, server temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Supported Models
| Model | Description | Modes | Image-to-Image | Max Images | Billing |
| ------------------------ | ------------------------------------------------------------ | ------------------------------ | -------------- | ---------- | -------------- |
| `gpt-image-1-official` | Stability-first, suitable for general image generation | Text-to-Image / Image-to-Image | Supported | 4 | Size x Quality |
| `gpt-image-1.5-official` | New version, suitable for higher quality and complex editing | Text-to-Image / Image-to-Image | Supported | 4 | Size x Quality |
## Authorizations
All API requests require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to obtain your API Key
Add the following to your request headers:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Model name
* `gpt-image-1-official` - Stability-first, suitable for general image generation
* `gpt-image-1.5-official` - New version, suitable for higher quality and complex editing
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation, supports both Chinese and English
Aspect ratio
Supported ratios:
* `1:1` - Square (default)
* `3:2` - Landscape
* `2:3` - Portrait
Number of images to generate
Range: 1-4
* Values ≤ 0 will be treated as `1`
* Values > 4 will be treated as `4`
**Warning:** Must be a plain number (e.g. `1`), do not add quotes, otherwise it will cause an error
Image quality
* `auto` - Auto quality selection (default)
* `low` - Faster, more economical
* `medium` - Balance between quality and cost
* `high` - Higher quality, higher cost
Background mode
* `auto` - Auto background (default)
* `opaque` - Opaque background
* `transparent` - Transparent background, recommended with `png` output format
`background: transparent` cannot be used with `output_format: jpeg` simultaneously
Moderation level
* `auto` - Default moderation level
* `low` - More lenient moderation
Output format
* `png` - Default format, suitable for transparent backgrounds
* `jpeg` - Smaller file size, suitable for general image output
`background: transparent` cannot be used with `output_format: jpeg` simultaneously
Output compression level, range 0-100
* Recommended only for `jpeg`
* Not recommended for `png`
Array of reference image URLs, enables image-to-image mode when provided
* 1 image for single reference editing
* 2-15 images for multi-reference fusion editing
* More than 15 images will be rejected
* Must be publicly accessible, stable image URLs
**Limit:** Up to 15 reference images
Mask image URL for inpainting
* Must be used together with `image_urls`
* Will be submitted via the official editing API
1. Before uploading the mask image, please confirm that the image Alpha channel is "Yes".
2. The mask image size must match the first reference image.
## Size Reference
Aspect ratios are used externally; the system automatically maps them to official dimensions internally.
| Ratio | Actual Size | Description |
| ----- | ----------- | ----------- |
| `1:1` | 1024x1024 | Square |
| `2:3` | 1024x1536 | Portrait |
| `3:2` | 1536x1024 | Landscape |
## Usage Examples
**Text-to-Image (minimal)**
```json theme={null}
{
"model": "gpt-image-1-official",
"prompt": "An ancient castle under a starry sky"
}
```
**Text-to-Image (full parameters)**
```json theme={null}
{
"model": "gpt-image-1-official",
"prompt": "A flat icon of a glass bottle with no background",
"size": "2:3",
"quality": "high",
"background": "transparent",
"moderation": "low",
"output_format": "png",
"n": 1
}
```
**Image-to-Image (single reference)**
```json theme={null}
{
"model": "gpt-image-1.5-official",
"prompt": "Convert the reference image to illustration style, preserving the main outline",
"size": "1:1",
"quality": "auto",
"image_urls": [
"https://your-cdn.com/input.png"
],
"n": 1
}
```
**Image-to-Image (multi-reference fusion)**
```json theme={null}
{
"model": "gpt-image-1.5-official",
"prompt": "Merge two reference images into an illustration poster, preserving the main outlines",
"size": "1:1",
"quality": "auto",
"background": "transparent",
"image_urls": [
"https://your-cdn.com/input-a.png",
"https://your-cdn.com/input-b.png"
],
"moderation": "low",
"output_format": "png",
"n": 1
}
```
**Multiple images (n > 1)**
```json theme={null}
{
"model": "gpt-image-1-official",
"prompt": "Four minimalist poster variations of a red fox",
"size": "1:1",
"quality": "low",
"output_format": "png",
"n": 4
}
```
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
## Notes
1. **Asynchronous processing**: After submission, a `task_id` is returned. Poll `/v1/tasks/{task_id}` to get results
2. **Model selection**: Use `gpt-image-1-official` for general image generation; use `gpt-image-1.5-official` for high-quality editing and complex image-to-image tasks
3. **Image URL requirements**: For image-to-image, use publicly accessible and stable image URLs
4. **Billing**: Charged per successfully generated image; no charge for failures
# GPT-Image-2.5 Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/gpt-image-2.5/generation
POST https://api.apimart.ai/v1/images/generations
- Choose between gpt-image-2.5-flare and gpt-image-2.5-sunburst
- Asynchronous processing returns a task_id for status queries
- Supports text-to-image and image editing with up to 16 reference images
- Supports 15 aspect ratios, exact pixel dimensions, and 1K / 2K / 4K resolution tiers
- Supports low / medium / high / xhigh / max quality levels
**Model selection:** `gpt-image-2.5-flare` is faster and works well for everyday high-quality images, batch generation, and rapid prototyping. `gpt-image-2.5-sunburst` prioritizes editing precision for production assets, advertising creatives, and detailed multi-turn editing. Both models use the same pricing.
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gpt-image-2.5-flare",
"prompt": "a cozy reading nook by a rainy window, warm lamp light, cinematic lighting",
"size": "1:1",
"resolution": "1k",
"quality": "medium",
"n": 1
}'
```
```python Python theme={null}
import requests
response = requests.post(
"https://api.apimart.ai/v1/images/generations",
headers={
"Authorization": "Bearer ",
"Content-Type": "application/json",
},
json={
"model": "gpt-image-2.5-flare",
"prompt": "a cozy reading nook by a rainy window, warm lamp light, cinematic lighting",
"size": "1:1",
"resolution": "1k",
"quality": "medium",
"n": 1,
},
)
print(response.json())
```
```javascript JavaScript theme={null}
const response = await fetch(
"https://api.apimart.ai/v1/images/generations",
{
method: "POST",
headers: {
Authorization: "Bearer ",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gpt-image-2.5-flare",
prompt: "a cozy reading nook by a rainy window, warm lamp light, cinematic lighting",
size: "1:1",
resolution: "1k",
quality: "medium",
n: 1,
}),
},
);
console.log(await response.json());
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KXXXXXXXXXXXXXXX"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Check your API key.",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests. Try again later.",
"type": "rate_limit_error"
}
}
```
## Authentication
All endpoints use Bearer Token authentication. Get your key from the [API Key page](https://apimart.ai/keys).
```
Authorization: Bearer YOUR_API_KEY
```
## Choose a model
| Model | Strength | Recommended use |
| ------------------------ | ------------------------------------- | ------------------------------------------------------------------------------------- |
| `gpt-image-2.5-flare` | Default option with faster generation | Social content, product images, visual search, rapid prototypes, and batch generation |
| `gpt-image-2.5-sunburst` | Prioritizes editing precision | Production product images, advertising creatives, and detailed multi-turn editing |
The two models have identical token usage and pricing for the same parameters. Select one based on the speed-versus-quality tradeoff.
Compared with `gpt-image-2`, GPT-Image-2.5 adds the `xhigh` and `max` quality levels. Its `medium` and `high` levels use roughly one quarter of the output tokens of the previous generation's levels with the same names.
## Request parameters
Image model name: `gpt-image-2.5-flare` or `gpt-image-2.5-sunburst`.
Text description of the image to generate or edit. Describe the subject, scene, composition, style, lighting, and anything that must be preserved or changed.
Output aspect ratio or exact pixel dimensions.
* `auto`: let the model choose from the prompt or reference images
* Aspect ratio: `1:1`, `3:2`, `2:3`, `4:3`, `3:4`, `5:4`, `4:5`, `16:9`, `9:16`, `2:1`, `1:2`, `21:9`, `9:21`, `3:1`, `1:3`
* Exact dimensions, such as `1600x1200`
For image-to-image requests, omit `size` to let the service calculate dimensions from the input aspect ratio and `resolution`.
Resolution tier used with an aspect-ratio `size`: `1k`, `2k`, or `4k`. This field is ignored for exact pixel dimensions.
Image quality: `low`, `medium`, `high`, `xhigh`, `max`, or `auto`.
`xhigh` and `max` are exclusive to GPT-Image-2.5. Sending them to `gpt-image-2` returns HTTP 400; the request is not silently downgraded.
Number of images to generate. Range: `1` to `4`. Pass a number, not a string.
Output file format: `png`, `jpeg`, or `webp`.
Compression level from `0` to `100`. Only applies to `jpeg` and `webp`.
Background mode: `transparent`, `opaque`, or `auto`.
`background: "transparent"` requires `output_format: "png"` or `output_format: "webp"`. JPEG has no alpha channel.
Content moderation level: `auto` or `low`. APIMart explicitly sends `low` when omitted; an explicit `auto` value is passed through.
Reference image URLs for image-to-image generation or editing. Up to `16` images are accepted, and including this field activates editing mode.
Only publicly accessible HTTP(S) URLs are accepted. Upload local images with `POST /v1/uploads/images`, then use the returned `url`.
## Size rules
Exact pixel dimensions must satisfy all of these constraints:
* Width and height are both multiples of `16`
* Neither side exceeds `3840` pixels
* Long-side to short-side ratio is at most `3:1`
* Total pixel count is between `655,360` and `8,294,400`
Resolutions above 2560×1440 are experimental and may be less stable than common sizes.
### Aspect ratio and resolution mapping
| `size` | `1k` | `2k` | `4k` |
| ------ | --------- | --------- | --------- |
| `1:1` | 1024×1024 | 2048×2048 | 2880×2880 |
| `3:2` | 1536×1024 | 2048×1360 | 3520×2336 |
| `2:3` | 1024×1536 | 1360×2048 | 2336×3520 |
| `4:3` | 1024×768 | 2048×1536 | 3312×2480 |
| `3:4` | 768×1024 | 1536×2048 | 2480×3312 |
| `5:4` | 1280×1024 | 2560×2048 | 3216×2576 |
| `4:5` | 1024×1280 | 2048×2560 | 2576×3216 |
| `16:9` | 1536×864 | 2048×1152 | 3840×2160 |
| `9:16` | 864×1536 | 1152×2048 | 2160×3840 |
| `2:1` | 2048×1024 | 2688×1344 | 3840×1920 |
| `1:2` | 1024×2048 | 1344×2688 | 1920×3840 |
| `21:9` | 2016×864 | 2688×1152 | 3840×1648 |
| `9:21` | 864×2016 | 1152×2688 | 1648×3840 |
| `3:1` | 1536×512 | 3072×1024 | 3840×1280 |
| `1:3` | 512×1536 | 1024×3072 | 1280×3840 |
You may also pass any exact dimensions that satisfy the size rules; they do not need to appear in this table.
## Usage examples
### Text to image
```json theme={null}
{
"model": "gpt-image-2.5-flare",
"prompt": "a sky garden in a futuristic city, morning mist, architectural photography",
"size": "16:9",
"resolution": "2k",
"quality": "high",
"n": 1
}
```
### Precision editing with Sunburst
```json theme={null}
{
"model": "gpt-image-2.5-sunburst",
"prompt": "preserve the product and package text, replace the background with a soft off-white studio, and add a natural shadow",
"image_urls": ["https://example.com/product.png"],
"resolution": "2k",
"quality": "xhigh"
}
```
### Transparent background
```json theme={null}
{
"model": "gpt-image-2.5-flare",
"prompt": "e-commerce product photo of white sneakers, complete subject, transparent background",
"size": "1:1",
"resolution": "2k",
"quality": "high",
"background": "transparent",
"output_format": "png"
}
```
## Submission and task query
Successful submission immediately returns an asynchronous task ID. `data` is an array; read `data[0].task_id`.
Call the [task status endpoint](/en/api-reference/tasks/status) with the returned ID. Poll every 2–5 seconds until the status becomes `completed` or `failed`. Use `POST /v1/tasks/batch` to query multiple tasks.
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KXXXXXXXXXXXXXXX",
"status": "completed",
"progress": 100,
"cost": 0.01325,
"credits_cost": 0.1325,
"result": {
"images": [
{
"url": ["https://upload.apimart.ai/f/image/example.png"],
"expires_at": 1789000000
}
]
},
"usage": {
"input_tokens": 16,
"output_tokens": 439,
"total_tokens": 455
}
}
}
```
Image URLs are located at `data.result.images[].url[]`. Download and store them promptly instead of relying on temporary URLs.
| Status | Meaning |
| ------------ | --------------------------------------------------------------------- |
| `submitted` | Task submitted |
| `processing` | Generation in progress |
| `completed` | Generation succeeded; `result.images` is available |
| `failed` | Generation failed; check `error.message`; reserved funds are refunded |
## Billing
GPT-Image-2.5 is billed by actual token usage. Flare and Sunburst use identical rates. Check the [pricing page](https://apimart.ai/pricing) or `/api/pricing` for current account pricing.
| Item | Price per 1M tokens |
| ------------------ | ------------------- |
| Image output | \$30.00 |
| Image input | \$8.00 |
| Cached image input | \$2.00 |
| Text input | \$5.00 |
| Cached text input | \$1.25 |
### 1024×1024 output token reference
| `quality` | Output tokens | Official output cost |
| --------- | ------------- | -------------------- |
| `low` | 196 | \$0.00588 |
| `medium` | 439 | \$0.01317 |
| `high` | 1756 | \$0.05268 |
| `xhigh` | 3122 | \$0.09366 |
| `max` | 7024 | \$0.21072 |
With `quality: "auto"`, the model chooses the actual level at runtime. The service reserves funds using the `max` level for the selected size and settles against actual usage when the task finishes. Specify `quality` when available balance matters.
For `n > 1`, the reservation scales linearly with the requested image count. Final billing uses the number of images actually generated, and failed tasks are refunded automatically.
## Output token reference
Values are per generated image. Actual billing also includes prompt and reference-image input tokens.
| Size | Pixels | low | medium | high | xhigh | max |
| --------- | --------- | --- | ------ | ---- | ----- | ----- |
| `1:1` | 1024×1024 | 196 | 439 | 1756 | 3122 | 7024 |
| `3:2` | 1536×1024 | 158 | 343 | 1372 | 2459 | 5488 |
| `2:3` | 1024×1536 | 158 | 343 | 1372 | 2459 | 5488 |
| `4:3` | 1024×768 | 134 | 301 | 1204 | 2140 | 4815 |
| `3:4` | 768×1024 | 134 | 301 | 1204 | 2140 | 4815 |
| `5:4` | 1280×1024 | 173 | 378 | 1510 | 2702 | 6119 |
| `4:5` | 1024×1280 | 173 | 378 | 1510 | 2702 | 6119 |
| `16:9` | 1536×864 | 120 | 280 | 1078 | 1917 | 4312 |
| `9:16` | 864×1536 | 120 | 280 | 1078 | 1917 | 4312 |
| `2:1` | 2048×1024 | 132 | 295 | 1180 | 2098 | 4720 |
| `1:2` | 1024×2048 | 132 | 295 | 1180 | 2098 | 4720 |
| `21:9` | 2016×864 | 105 | 225 | 943 | 1617 | 3682 |
| `9:21` | 864×2016 | 105 | 225 | 943 | 1617 | 3682 |
| `3:1` | 1536×512 | 56 | 134 | 535 | 937 | 2140 |
| `1:3` | 512×1536 | 56 | 134 | 535 | 937 | 2140 |
| `1:1@2k` | 2048×2048 | 397 | 892 | 3568 | 6343 | 14272 |
| `3:2@2k` | 2048×1360 | 211 | 460 | 1838 | 3216 | 7351 |
| `2:3@2k` | 1360×2048 | 211 | 460 | 1838 | 3216 | 7351 |
| `4:3@2k` | 2048×1536 | 247 | 556 | 2223 | 3952 | 8892 |
| `3:4@2k` | 1536×2048 | 247 | 556 | 2223 | 3952 | 8892 |
| `5:4@2k` | 2560×2048 | 377 | 826 | 3303 | 5911 | 13385 |
| `4:5@2k` | 2048×2560 | 377 | 826 | 3303 | 5911 | 13385 |
| `16:9@2k` | 2048×1152 | 157 | 367 | 1413 | 2511 | 5650 |
| `9:16@2k` | 1152×2048 | 157 | 367 | 1413 | 2511 | 5650 |
| `2:1@2k` | 2688×1344 | 180 | 405 | 1617 | 2874 | 6466 |
| `1:2@2k` | 1344×2688 | 180 | 405 | 1617 | 2874 | 6466 |
| `21:9@2k` | 2688×1152 | 143 | 306 | 1285 | 2202 | 5016 |
| `9:21@2k` | 1152×2688 | 143 | 306 | 1285 | 2202 | 5016 |
| `3:1@2k` | 3072×1024 | 103 | 247 | 988 | 1729 | 3952 |
| `1:3@2k` | 1024×3072 | 103 | 247 | 988 | 1729 | 3952 |
| `1:1@4k` | 2880×2880 | 659 | 1483 | 5930 | 10542 | 23719 |
| `3:2@4k` | 3520×2336 | 450 | 982 | 3926 | 6870 | 15703 |
| `2:3@4k` | 2336×3520 | 450 | 982 | 3926 | 6870 | 15703 |
| `4:3@4k` | 3312×2480 | 491 | 1104 | 4413 | 7845 | 17650 |
| `3:4@4k` | 2480×3312 | 491 | 1104 | 4413 | 7845 | 17650 |
| `5:4@4k` | 3216×2576 | 535 | 1173 | 4690 | 8393 | 19006 |
| `4:5@4k` | 2576×3216 | 535 | 1173 | 4690 | 8393 | 19006 |
| `16:9@4k` | 3840×2160 | 371 | 865 | 3336 | 5930 | 13342 |
| `9:16@4k` | 2160×3840 | 371 | 865 | 3336 | 5930 | 13342 |
| `2:1@4k` | 3840×1920 | 300 | 675 | 2700 | 4799 | 10798 |
| `1:2@4k` | 1920×3840 | 300 | 675 | 2700 | 4799 | 10798 |
| `21:9@4k` | 3840×1648 | 234 | 500 | 2099 | 3598 | 8196 |
| `9:21@4k` | 1648×3840 | 234 | 500 | 2099 | 3598 | 8196 |
| `3:1@4k` | 3840×1280 | 139 | 332 | 1328 | 2324 | 5311 |
| `1:3@4k` | 1280×3840 | 139 | 332 | 1328 | 2324 | 5311 |
## Limits and common errors
| Item | Limit or handling |
| ------------------------ | ------------------------------------------------------------ |
| Images per request (`n`) | 1–4 |
| Reference images | Up to 16 |
| Output format | PNG / JPEG / WebP |
| Transparent background | PNG / WebP only |
| Partial streaming images | Not supported |
| Unsupported `quality` | `xhigh` / `max` require GPT-Image-2.5 |
| Invalid exact dimensions | Use multiples of 16 within the pixel and aspect-ratio limits |
## Response
Response status code; 200 when submission succeeds.
Submission response data.
Initially `submitted`.
Unique task ID used to query generation status and results.
# GPT-Image-2 Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/gpt-image-2/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- OpenAI Images compatible protocol, supports text-to-image / image-to-image
- 15 image aspect ratios supported via the `size` field
- Output pixel tier controlled via `resolution` (`1k` / `2k` / `4k`)
- Up to 15 reference images, URL and base64 can be mixed
- Billed by resolution tier (1K / 2K / 4K)
**Model name compatibility note**: This endpoint also accepts the alias `gpt-image-2-ext`, which is equivalent to `gpt-image-2`. The two are interchangeable and produce identical results.
```bash cURL theme={null}
# model can be "gpt-image-2", or the compatible alias "gpt-image-2-ext"
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gpt-image-2",
"prompt": "A ginger cat sitting on a windowsill watching the sunset, watercolor style",
"n": 1,
"size": "16:9",
"resolution": "2k"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "gpt-image-2",
"prompt": "A ginger cat sitting on a windowsill watching the sunset, watercolor style",
"n": 1,
"size": "16:9",
"resolution": "2k"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "gpt-image-2",
prompt: "A ginger cat sitting on a windowsill watching the sunset, watercolor style",
n: 1,
size: "16:9",
resolution: "2k"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "gpt-image-2",
"prompt": "A ginger cat sitting on a windowsill watching the sunset, watercolor style",
"n": 1,
"size": "16:9",
"resolution": "2k",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "gpt-image-2",
"prompt": "A ginger cat sitting on a windowsill watching the sunset, watercolor style",
"n": 1,
"size": "16:9",
"resolution": "2k"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"gpt-image-2",
"prompt" => "A ginger cat sitting on a windowsill watching the sunset, watercolor style",
"n" => 1,
"size" => "16:9",
"resolution" => "2k"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "gpt-image-2",
prompt: "A ginger cat sitting on a windowsill watching the sunset, watercolor style",
n: 1,
size: "16:9",
resolution: "2k"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "gpt-image-2",
"prompt": "A ginger cat sitting on a windowsill watching the sunset, watercolor style",
"n": 1,
"size": "16:9",
"resolution": "2k"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""gpt-image-2"",
""prompt"": ""A ginger cat sitting on a windowsill watching the sunset, watercolor style"",
""n"": 1,
""size"": ""16:9"",
""resolution"": ""2k""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'gpt-image-2',
'prompt': 'A ginger cat sitting on a windowsill watching the sunset, watercolor style',
'n': 1,
'size': '16:9',
'resolution': '2k'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json'
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "gpt-image-2",
prompt = "A ginger cat sitting on a windowsill watching the sunset, watercolor style",
n = 1,
size = "16:9",
resolution = "2k"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KPQ7J7DWB7QZ3WCEK3YVPBRA"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid parameters: size not allowed / resolution not supported / pixel violation, etc.",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "build_request_failed: invalid size: 3:5, allowed: 1:1 / 16:9 / 9:16 / 4:3 / 3:4 / 3:2 / 2:3 / 5:4 / 4:5 / 2:1 / 1:2 / 3:1 / 1:3 / 21:9 / 9:21",
"type": "server_error"
}
}
```
```json 503 theme={null}
{
"error": {
"code": 503,
"message": "Upstream temporarily unavailable, please try again later",
"type": "service_unavailable"
}
}
```
## Authorizations
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Include it in the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
Fixed to `gpt-image-2` (compatible alias `gpt-image-2-ext`)
For backward compatibility, the alias `gpt-image-2-ext` (for `gpt-image-2`) remains usable.
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
* Supports English and Chinese, detailed descriptions recommended
* Pre-submission content moderation / safety review — violations are rejected immediately
Number of images to generate
Value: `1`
Must be a pure number (e.g., `1`), do not wrap in quotes
Image aspect ratio
Supported ratios, plus `auto` to let the server pick a suitable ratio automatically:
| size | Type |
| ------ | --------- |
| `auto` | Automatic |
| `1:1` | Square |
| `3:2` | Landscape |
| `2:3` | Portrait |
| `4:3` | Landscape |
| `3:4` | Portrait |
| `5:4` | Landscape |
| `4:5` | Portrait |
| `16:9` | Landscape |
| `9:16` | Portrait |
| `2:1` | Landscape |
| `1:2` | Portrait |
| `3:1` | Landscape |
| `1:3` | Portrait |
| `21:9` | Landscape |
| `9:21` | Portrait |
Pixel dimensions can also be passed directly, such as `1881x836` / `887x1774`.
When `size` is set to `auto`, the default ratio is `1:1`.
Output resolution tier
Options: `1k` / `2k` / `4k`
`size × resolution` → actual pixel mapping:
| size | `1k` | `2k` | `4k` |
| ------ | --------------------- | --------- | ------------- |
| `1:1` | 1024×1024 / 1254×1254 | 2048×2048 | **2880×2880** |
| `3:2` | 1536×1024 | 2048×1360 | **3520×2336** |
| `2:3` | 1024×1536 | 1360×2048 | **2336×3520** |
| `4:3` | 1024×768 | 2048×1536 | **3312×2480** |
| `3:4` | 768×1024 | 1536×2048 | **2480×3312** |
| `5:4` | 1280×1024 / 1448×1086 | 2560×2048 | **3216×2576** |
| `4:5` | 1024×1280 / 1122×1402 | 2048×2560 | **2576×3216** |
| `16:9` | 1536×864 / 1672×941 | 2048×1152 | **3840×2160** |
| `9:16` | 864×1536 / 941×1672 | 1152×2048 | **2160×3840** |
| `2:1` | 2048×1024 / 1774×887 | 2688×1344 | **3840×1920** |
| `1:2` | 1024×2048 / 887×1774 | 1344×2688 | **1920×3840** |
| `3:1` | 1881×836 / 1536×512 | 3072×1024 | **3840×1280** |
| `1:3` | 887×1774 / 512×1536 | 1024×3072 | **1280×3840** |
| `21:9` | 2016×864 / 1915×821 | 2688×1152 | **3840×1648** |
| `9:21` | 864×2016 / 821×1915 | 1152×2688 | **1648×3840** |
4K supports the 15 ratios listed above; you can also pass the pixel dimensions from the table directly via `size`.
Reference image array (OpenAI standard field). Switches to image-to-image mode when provided.
* Up to 15 reference images, exceeding returns `image_urls exceeds max 15`
* Max 20 MB per image, 256 MB in total
* Supports `image URL` (public stable link)
* Supports `base64 data URI` (e.g. `data:image/png;base64,...`)
* URL and base64 can be mixed in the same array, handled by the server
* Without `size`, output resolution = input image resolution; with `size`, output is forced to the specified ratio
Other OpenAI standard fields (`response_format`, `style`) are not supported and will be ignored. Task results only return `url` — please download and convert to base64 yourself if needed.
Whether to fall back to the official channel
* `false`: Do not use (default)
* `true`: Use the official channel
## Usage Examples
**Text-to-image (minimal request)**
```json theme={null}
{
"model": "gpt-image-2",
"prompt": "A ginger cat sitting on a windowsill watching the sunset, watercolor style"
}
```
**Text-to-image (with ratio + 2K)**
```json theme={null}
{
"model": "gpt-image-2",
"prompt": "a corgi astronaut on the moon, cinematic, 8k",
"size": "16:9",
"resolution": "2k"
}
```
**Text-to-image (4K output)**
```json theme={null}
{
"model": "gpt-image-2",
"prompt": "An ancient castle under a starry sky",
"size": "16:9",
"resolution": "4k"
}
```
**Text-to-image (multiple images)**
```json theme={null}
{
"model": "gpt-image-2",
"prompt": "An ancient castle under a starry sky",
"size": "16:9",
"resolution": "4k",
"n": 2
}
```
**Image-to-image (reference = URL)**
```json theme={null}
{
"model": "gpt-image-2",
"prompt": "Turn this photo into a watercolor painting",
"image_urls": [
"https://example.com/photo.jpg"
]
}
```
**Image-to-image (reference = base64)**
```json theme={null}
{
"model": "gpt-image-2",
"prompt": "Turn this photo into a watercolor painting",
"image_urls": [
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
]
}
```
**Image-to-image (multi-reference fusion, URL + base64 mixed)**
```json theme={null}
{
"model": "gpt-image-2",
"prompt": "Fuse these two photos into a single poster",
"size": "4:3",
"resolution": "2k",
"image_urls": [
"https://example.com/photo-a.jpg",
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
]
}
```
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier, used for subsequent result queries
## Querying Task Results
After successful submission, a `task_id` is returned. Poll the task status via `GET /v1/tasks/{task_id}`, see [Task Query API](/en/api-reference/tasks/status) for details.
### Success Response Example
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KPQ7J7DWB7QZ3WCEK3YVPBRA",
"status": "completed",
"progress": 100,
"created": 1776748674,
"completed": 1776748726,
"actual_time": 52,
"cost": 0.05279,
"credits_cost": 0.5279,
"estimated_time": 100,
"result": {
"images": [
{
"url": [
"https://upload.apimart.ai/f/image/xxxxxxxx-gpt_image_2_task_xxx_0.png"
],
"expires_at": 1776835126
}
]
}
}
}
```
Image access: `data.result.images[0].url[0]`
### Task Status
| Status | Meaning |
| ------------ | ---------------------------------- |
| `submitted` | Submitted |
| `processing` | Being processed upstream |
| `completed` | Success, `result.images` available |
| `failed` | Failed, check `error.message` |
# GPT-Image-2 Official Channel Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/gpt-image-2/official
POST https://api.apimart.ai/v1/images/generations
- OpenAI official `gpt-image-2` model, based on `/v1/images/generations` compatible protocol
- Asynchronous processing, returns `task_id` for subsequent queries
- Text-to-image / image-to-image / inpainting (mask) — all-in-one
- Supports PNG / WebP transparent backgrounds (Alpha channel)
- New `resolution` tier field — 1K / 2K / 4K selection
- 15 aspect ratios supported across the 1K / 2K / 4K tiers
- Up to 4 images per request, up to 16 reference images
- 95% parameter alignment with `gpt-image-1.5-official` — migration only requires changing the model name
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gpt-image-2-official",
"prompt": "An ancient castle beneath a starry sky",
"size": "16:9",
"resolution": "2k",
"quality": "high",
"n": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "gpt-image-2-official",
"prompt": "An ancient castle beneath a starry sky",
"size": "16:9",
"resolution": "2k",
"quality": "high",
"n": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "gpt-image-2-official",
prompt: "An ancient castle beneath a starry sky",
size: "16:9",
resolution: "2k",
quality: "high",
n: 1,
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "gpt-image-2-official",
"prompt": "An ancient castle beneath a starry sky",
"size": "16:9",
"resolution": "2k",
"quality": "high",
"n": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "gpt-image-2-official",
"prompt": "An ancient castle beneath a starry sky",
"size": "16:9",
"resolution": "2k",
"quality": "high",
"n": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"gpt-image-2-official",
"prompt" => "An ancient castle beneath a starry sky",
"size" => "16:9",
"resolution" => "2k",
"quality" => "high",
"n" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "gpt-image-2-official",
prompt: "An ancient castle beneath a starry sky",
size: "16:9",
resolution: "2k",
quality: "high",
n: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "gpt-image-2-official",
"prompt": "An ancient castle beneath a starry sky",
"size": "16:9",
"resolution": "2k",
"quality": "high",
"n": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""gpt-image-2-official"",
""prompt"": ""An ancient castle beneath a starry sky"",
""size"": ""16:9"",
""resolution"": ""2k"",
""quality"": ""high"",
""n"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'gpt-image-2-official',
'prompt': 'An ancient castle beneath a starry sky',
'size': '16:9',
'resolution': '2k',
'quality': 'high',
'n': 1,
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "gpt-image-2-official",
prompt = "An ancient castle beneath a starry sky",
size = "16:9",
resolution = "2k",
quality = "high",
n = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KPTXXXXXXXXXXXXXXX"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid parameters: size not allowed / resolution not supported / pixel violation, etc.",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Include it in the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
Fixed to `gpt-image-2-official` (OpenAI official gpt-image-2 model)
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
* Supports English and Chinese, detailed descriptions recommended
* Pre-submission content moderation / safety review — violations are rejected immediately
Image aspect ratio
Externally uses ratio values; internally mapped to actual pixels according to `resolution`.
Supported ratios, plus `auto` to let the server pick a suitable ratio automatically:
* `auto` - Automatic (server picks a ratio based on prompt / reference images)
* `1:1` - Square (default, social avatars / logos)
* `3:2` - Landscape (common DSLR ratio)
* `2:3` - Portrait (vertical posters)
* `4:3` - Landscape (classic monitor / slideshow)
* `3:4` - Portrait
* `5:4` - Landscape
* `4:5` - Portrait (Instagram vertical post)
* `16:9` - Landscape (widescreen video thumbnail)
* `9:16` - Portrait (phone full-screen / short video cover)
* `2:1` - Landscape (web banner)
* `1:2` - Portrait
* `3:1` - Landscape (ultra-wide banner)
* `1:3` - Portrait (extra-tall poster)
* `21:9` - Landscape (cinematic ultra-wide)
* `9:21` - Portrait
Pixel dimensions can also be passed directly, such as `1881x836` / `887x1774`.
When `size` is set to `auto`, the default ratio is `1:1`.
Resolution tier (**new field**)
Controls the actual output clarity.
* `1k` - 1024 baseline, cost-efficient for daily use (default)
* `2k` - 2048 baseline, suitable for posters / high-definition needs
* `4k` - 3840 baseline, supports the 15 ratios in the mapping table below
4K supports the 15 ratios in the mapping table below; you can also pass the pixel dimensions from the table directly via `size`.
Image quality
* `auto` - Automatic (default, typically equivalent to `low`)
* `low` - Fast and economical, sufficient for rough outlines
* `medium` - Balanced
* `high` - Maximum precision (4K + high can take >120s)
Background mode
* `auto` - Automatic (default)
* `opaque` - Opaque
* `transparent` - Requests a transparent background; the output includes an Alpha channel
Moderation strength
* `auto` - Default moderation strength
* `low` - More lenient moderation
Output format
* `png` - Default format; supports transparent backgrounds
* `jpeg` - Smaller files; does not support an Alpha channel
* `webp` - Supports transparent backgrounds; suitable for modern browsers
When `background` is `transparent`, only `png` or `webp` can be selected.
Output compression level, range `0-100`
* Only effective for `jpeg` / `webp`
Number of images to generate
Range: `1 ~ 4`
Must be a pure number (e.g., `1`), do not wrap in quotes
Reference image URL array
* Up to 20 MB per image, 256 MB total cap
* Up to **16** reference images; more will be rejected
* Must be publicly accessible, stable image URLs
Mask image URL, used for inpainting
* Must be used together with `image_urls`
1. Ensure the mask image has an Alpha channel before uploading.
2. The mask image dimensions must **match the first reference image**.
## Size × Resolution Mapping
`size × resolution` → OpenAI actual pixels (15 ratios × 3 tiers):
| size | `1k` | `2k` | `4k` |
| ------ | ------------------- | --------- | ------------- |
| `1:1` | 1024×1024 | 2048×2048 | **2880×2880** |
| `3:2` | 1536×1024 | 2048×1360 | **3520×2336** |
| `2:3` | 1024×1536 | 1360×2048 | **2336×3520** |
| `4:3` | 1024×768 | 2048×1536 | **3312×2480** |
| `3:4` | 768×1024 | 1536×2048 | **2480×3312** |
| `5:4` | 1280×1024 | 2560×2048 | **3216×2576** |
| `4:5` | 1024×1280 | 2048×2560 | **2576×3216** |
| `16:9` | 1536×864 | 2048×1152 | **3840×2160** |
| `9:16` | 864×1536 | 1152×2048 | **2160×3840** |
| `2:1` | 2048×1024 | 2688×1344 | **3840×1920** |
| `1:2` | 1024×2048 | 1344×2688 | **1920×3840** |
| `3:1` | 1881×836 / 1536×512 | 3072×1024 | **3840×1280** |
| `1:3` | 887×1774 / 512×1536 | 1024×3072 | **1280×3840** |
| `21:9` | 2016×864 | 2688×1152 | **3840×1648** |
| `9:21` | 864×2016 | 1152×2688 | **1648×3840** |
> Note: Some dimensions are approximated based on multiples of 16 and pixel limits, such as `3:2` / `2:3` @ 2K being 2048×1360 and `21:9` @ 4K being 3840×1648. Use the actual pixels in the table as the source of truth.
## Usage Examples
**Text-to-image (minimal request)**
```json theme={null}
{
"model": "gpt-image-2-official",
"prompt": "An ancient castle beneath a starry sky"
}
```
**Text-to-image (transparent sticker)**
```json theme={null}
{
"model": "gpt-image-2-official",
"prompt": "A cute cartoon orange cat sticker, full body, thick white outline, flat vector style, isolated on a fully transparent background",
"size": "1:1",
"resolution": "1k",
"quality": "medium",
"background": "transparent",
"output_format": "png",
"n": 1
}
```
**Image-to-image (remove background)**
```json theme={null}
{
"model": "gpt-image-2-official",
"prompt": "Remove the background, keep only the product, isolated on a fully transparent background",
"image_urls": ["https://your-cdn.com/product.jpg"],
"size": "1:1",
"resolution": "1k",
"background": "transparent",
"output_format": "png"
}
```
**2K high-definition poster**
```json theme={null}
{
"model": "gpt-image-2-official",
"prompt": "Cyberpunk night scene",
"size": "16:9",
"resolution": "2k",
"quality": "high",
"output_format": "jpeg",
"output_compression": 90
}
```
**4K wallpaper**
```json theme={null}
{
"model": "gpt-image-2-official",
"prompt": "Snow mountain sunrise panorama",
"size": "16:9",
"resolution": "4k",
"quality": "high",
"n": 1
}
```
**Image-to-image (multi-reference fusion)**
```json theme={null}
{
"model": "gpt-image-2-official",
"prompt": "Fuse the two reference images into a single illustration poster, preserving the main silhouettes",
"size": "1:1",
"quality": "high",
"image_urls": [
"https://your-cdn.com/input-a.png",
"https://your-cdn.com/input-b.png"
]
}
```
**Inpainting (mask)**
```json theme={null}
{
"model": "gpt-image-2-official",
"prompt": "Replace the background with a desert sunset",
"size": "1:1",
"quality": "medium",
"image_urls": ["https://your-cdn.com/photo.png"],
"mask_url": "https://your-cdn.com/mask.png"
}
```
**Multiple images (n > 1)**
```json theme={null}
{
"model": "gpt-image-2-official",
"prompt": "Four minimalist poster variations of a red fox",
"size": "1:1",
"quality": "low",
"n": 4
}
```
**Direct pixel string (advanced)**
```json theme={null}
{
"model": "gpt-image-2-official",
"prompt": "wide cinematic shot",
"size": "3840x2160",
"quality": "high"
}
```
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier, used for subsequent result queries
## Querying Task Results
After successful submission, a `task_id` is returned. Poll the task status via `GET /v1/tasks/{task_id}`, see [Task Query API](/en/api-reference/tasks/status) for details.
### Success Response Example
```json theme={null}
{
"code": 200,
"data": {
"actual_time": 14,
"completed": 1784607890,
"cost": 0.004792,
"created": 1784607876,
"credits_cost": 0.047920000000000004,
"estimated_time": 60,
"id": "task_01KPTXXXXXXXXXXXXXXX",
"progress": 100,
"result": {
"images": [
{
"expires_at": 1784694290,
"url": [
"https://upload.apimart.ai/f/image/xxxxxxxx-gpt_image_2_official_task_xxx_0.png"
]
}
]
},
"status": "completed",
"usage": {
"input_tokens": 22,
"input_tokens_details": {
"cached_tokens": 0,
"image_tokens": 0,
"text_tokens": 22
},
"output_tokens": 196,
"output_tokens_details": {
"image_tokens": 196,
"text_tokens": 0
},
"total_tokens": 218
}
}
}
```
The `usage` field reports the billable token usage for this request:
| Field | Description |
| ------------------------------------ | ------------------------------------------------------- |
| `input_tokens` | Total input tokens consumed |
| `input_tokens_details.cached_tokens` | Input tokens served from cache |
| `input_tokens_details.image_tokens` | Tokens used by input images |
| `input_tokens_details.text_tokens` | Tokens used by input text (prompt) |
| `output_tokens` | Total output tokens consumed |
| `output_tokens_details.image_tokens` | Tokens used by the generated image |
| `output_tokens_details.text_tokens` | Tokens used by output text |
| `total_tokens` | Total tokens, equal to `input_tokens` + `output_tokens` |
For image generation the output is mostly image tokens, so `output_tokens_details.image_tokens` usually equals `output_tokens`. In the example above, `total_tokens` = 22 + 196 = 218.
Task status flow: `submitted` → `in_progress` → `completed` / `failed`.
Image access: `data.result.images[0].url[0]`.
# Grok Imagine 2.0 Ext Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/grok-imagine-2.0-ext/generation
POST https://api.apimart.ai/v1/images/generations
- Async text-to-image; poll with task_id
- 1–12 images per request; billed per successfully delivered image ($0.08 each)
- URL output only; no image-to-image / streaming
- Image URLs expire in 72 hours
**Text-to-image · async jobs.** Submit `POST /v1/images/generations`, then poll [Get task status](/en/api-reference/tasks/status).\
Model name is fixed `grok-imagine-2.0-ext`. **Not supported**: reference images, `stream`, or `response_format` values other than `url`.
For object layers or selected-region editing, see [Layers and region editing](/en/api-reference/images/grok-imagine-2.0-ext/layer-region-edit).
Do not put API keys in browser bundles (`VITE_*` / `NEXT_PUBLIC_*`, LocalStorage, etc.). Prefer calling your own BFF from the browser; keep the APIMart key on the server.
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Idempotency-Key: 8eacb46d-ef4e-4f4e-82de-830bd8bc67e2' \
--header 'X-APIMart-Response-Version: 2026-07-27' \
--data '{
"model": "grok-imagine-2.0-ext",
"prompt": "A red apple on a white ceramic plate, clean studio product photo",
"n": 1,
"size": "1:1",
"resolution": "quality",
"response_format": "url"
}'
```
```python Python theme={null}
import requests
import uuid
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "grok-imagine-2.0-ext",
"prompt": "A red apple on a white ceramic plate, clean studio product photo",
"n": 1,
"size": "1:1",
"resolution": "quality",
"response_format": "url",
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json",
"Accept": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
"X-APIMart-Response-Version": "2026-07-27",
}
response = requests.post(url, json=payload, headers=headers)
print(response.status_code, response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "grok-imagine-2.0-ext",
prompt: "A red apple on a white ceramic plate, clean studio product photo",
n: 1,
size: "1:1",
resolution: "quality",
response_format: "url",
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
Accept: "application/json",
"Idempotency-Key": crypto.randomUUID(),
"X-APIMart-Response-Version": "2026-07-27",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then(async (response) => {
console.log(response.status, await response.json());
})
.catch((error) => console.error("Error:", error));
```
```json 202 theme={null}
{
"code": 202,
"request_id": "2026081111342261665927mpb4IPDb",
"data": {
"id": "task_01KZQE5CM0Y3KZ6M1N1BK619MX",
"object": "generation.task",
"type": "image",
"status": "pending",
"progress": 0,
"poll_url": "/v1/tasks/task_01KZQE5CM0Y3KZ6M1N1BK619MX"
}
}
```
```json 400 theme={null}
{
"request_id": "20260811...",
"error": {
"message": "`response_format` for grok-imagine-2.0-ext only supports `url` (got: b64_json)",
"type": "invalid_response_format",
"param": "",
"code": "invalid_response_format"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up and try again",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests. Please try again later",
"type": "rate_limit_error"
}
}
```
## Capabilities and limits
| Dimension | Contract |
| ------------- | ------------------------------------------------------------------------------- |
| Model | Fixed `grok-imagine-2.0-ext` |
| Capability | **Text-to-image only** |
| Mode | Async task |
| Count `n` | `1`–`12`, default `1` |
| `size` | 7 aspect ratios + 5 pixel aliases (below) |
| Output | `response_format=url` only (also the default) |
| Quality | Public field `resolution`; verified value `quality` |
| Not supported | Image-to-image, `stream=true`, public `quality`, `style`, `b64_json` / `base64` |
| Billing | Fixed unit price; charge **successfully delivered** images |
## Auth and recommended headers
Bearer token. Get a key from the [API Key page](https://apimart.ai/keys).
```
Authorization: Bearer YOUR_API_KEY
```
| Header | Notes |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `Content-Type` | `application/json` (submit) |
| `Accept` | `application/json` |
| `Idempotency-Key` | Strongly recommended. New UUID per user-confirmed generation; network retries **must reuse** the same key and body |
| `X-APIMart-Response-Version` | Prefer `2026-07-27` for a stable submit shape (`data.id`) |
## Request parameters
Fixed value: `grok-imagine-2.0-ext`
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Prompt. Must be non-empty after trim. Trim before submit.
Image count: `1`–`12`. Explicit `0` errors. Omit for `1`.
Aspect ratio. **Prefer ratio strings** (UI should only show ratios):
| `size` | Orientation | Typical use |
| ------ | ----------- | ------------------------- |
| `1:1` | Square | Product, avatar |
| `2:3` | Portrait | Poster, full-body |
| `3:2` | Landscape | Photo, wide scene |
| `3:4` | Portrait | E-commerce, people |
| `4:3` | Landscape | Display art |
| `9:16` | Vertical | Story / short-video cover |
| `16:9` | Wide | Banner, video cover |
Pixel aliases: `1024x1024` (1:1), `1024x1792` (2:3), `1792x1024` (3:2), `720x1280` (9:16), `1280x720` (16:9).
Values outside the whitelist return `400 invalid_size` (e.g. `1:2`, `2:1`, `4:5`, `auto`).
Actual pixels for a given ratio may differ from the alias table (e.g. `1:1` may return 1408×1408). Trust the returned image; do not rewrite `size` from measured pixels.
Quality-mode field. Verified value: `quality`.
* Omit (model is quality-mode by default), or
* Pass `resolution: "quality"` explicitly
**Not** a `1K` / `2K` / `4K` pixel tier; framing is controlled by `size`.
Do not send a public `quality` field — you get `400 invalid_quality`. Use `resolution`.
Only `url` is allowed. May be omitted. `b64_json` / `base64` → `400 invalid_response_format`.
Optional public HTTPS **base URL**. On terminal status the platform POSTs `{webhook}/callback`. Server-side only — see [Webhook](#webhook-optional).
### Unsupported parameters
| Parameter | Behavior |
| ------------------------------------------ | ---------------------------------------- |
| `quality` | `400 invalid_quality` → use `resolution` |
| `style` | `400 invalid_style` |
| `image_urls` / `image_with_roles` | `400 invalid_image_input` |
| `stream: true` | `400 invalid_stream` |
| `response_format: "b64_json"` / `"base64"` | `400 invalid_response_format` |
Build requests with a whitelist; do not forward a generic image-form object from other models.
## Request examples
### Minimal
```json theme={null}
{
"model": "grok-imagine-2.0-ext",
"prompt": "A red apple on a white ceramic plate, clean studio product photo"
}
```
### Recommended
```json theme={null}
{
"model": "grok-imagine-2.0-ext",
"prompt": "A red apple on a white ceramic plate, clean studio product photo",
"n": 1,
"size": "1:1",
"resolution": "quality",
"response_format": "url"
}
```
## Submit response
Prefer `X-APIMart-Response-Version: 2026-07-27`. Success is HTTP **`202`**; task id is **`data.id`** (do not rely on legacy `data[0].task_id`).
Persist:
* `data.id` for polling
* `request_id` for gateway debugging
* the `Idempotency-Key` for safe retries when outcome is unknown
* original request params for UI / support
## Idempotency and safe retries
Image generation is billable — **strongly recommend** `Idempotency-Key` (1–191 printable ASCII chars; UUID is easiest; retained \~24 hours).
| Scenario | Behavior | Action |
| --------------------------------- | --------------------------------------------- | --------------------------------------------------- |
| Same key + same body already done | Replay; header `Idempotency-Replayed: true` | Use the same task id |
| Same key still in flight | `409 idempotency_in_progress` + `Retry-After` | Wait, retry **same key and body** |
| Same key, different body | `409 idempotency_key_reused` | New logical job needs a new key |
| Outcome indeterminate | `409 idempotency_result_indeterminate` | Do not mint a new key; investigate with the old one |
On POST network timeout when you cannot tell if the server accepted the job, **do not immediately create a new key** — retry with the same key / body / response version.
## Poll tasks
```http theme={null}
GET /v1/tasks/{task_id}?language=en
Authorization: Bearer YOUR_API_KEY
Accept: application/json
```
Optional `language`: `zh` / `en` / `ko` / `ja` (failure message localization only). See [Get task status](/en/api-reference/tasks/status).
### Statuses
| `status` | Terminal | Handling |
| ------------------------ | :------: | --------------------------------------------------------------- |
| `pending` / `processing` | No | Keep polling (`result` may be absent — not a failure) |
| `completed` | Yes | Parse `result.images` |
| `failed` | Yes | Show `error.message`; `cost` is `0` (pre-charge refunded) |
| `unknown` | No | Short retries; if it persists, contact support with the task id |
Poll about every **2 seconds**; cap near **10 minutes** or **120** attempts. Honor `Retry-After` on `429`. Tasks are kept \~3 days by default — keep the task id if the client times out.
### Completed example
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KZQE5CM0Y3KZ6M1N1BK619MX",
"status": "completed",
"progress": 100,
"created": 1786419262,
"completed": 1786419275,
"actual_time": 13,
"estimated_time": 100,
"cost": 0.08,
"credits_cost": 0.8,
"result": {
"images": [
{
"expires_at": 1786505675,
"url": [
"https://example.com/image/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.jpg"
],
"image_ids": [
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
]
}
]
}
}
}
```
### Parsing `url` and `image_ids`
```text theme={null}
result.images[]
├─ url[] ← authoritative display/download field (array)
├─ image_ids[] ← optional opaque IDs
└─ expires_at ← Unix seconds; multiply by 1000 for JS Date
```
1. Use `url[]` for display; when `n>1`, walk all entries
2. Pair by index only if `image_ids.length === url.length`
3. Missing `image_ids` still allows display
4. Links last **72 hours** — download promptly; also trust `expires_at`
## Billing
Base price **\$0.08 per image** (successful deliveries):
| `n` | Estimated base |
| --: | -------------: |
| 1 | \$0.08 |
| 4 | \$0.32 |
| 8 | \$0.64 |
| 12 | \$0.96 |
* Pre-submit UI should say “estimate”; final USD is **`data.cost`**
* **`data.credits_cost`** is the credits view (currently \~ USD × 10)
* Pre-charge by requested count; settle on successful count (partial refunds if partial failure)
* Full failure: `cost=0`, pre-charge refunded
* Do not build price keys from `resolution`; this model is flat per image
## Webhook (optional)
```json theme={null}
{
"webhook": "https://your-service.example.com/apimart"
}
```
* Provide a **base URL**; the platform calls `{base}/callback`
* Must be public and pass SSRF checks
* If `webhook_secret` is set, signature is `hex(HMAC-SHA256(secret, raw_body))` over raw bytes
* Callback body matches task query `data` (no extra `{code,data}` wrapper)
* Still keep low-frequency polling as a fallback
## Common errors
| HTTP | `error.code` | Cause | Action |
| ---: | ------------------------- | ----------------------- | ------------------------------------------- |
| 400 | `invalid_request` | Empty prompt / bad JSON | Validate input |
| 400 | `invalid_n` | `n` outside 1–12 | Clamp count |
| 400 | `invalid_size` | Size not whitelisted | Fixed select options |
| 400 | `invalid_response_format` | Not `url` | Fix or omit |
| 400 | `invalid_quality` | Public `quality` sent | Use `resolution` |
| 400 | `invalid_style` | `style` sent | Remove |
| 400 | `invalid_image_input` | Reference images | Switch models |
| 400 | `invalid_stream` | `stream=true` | Remove |
| 400 | `invalid_idempotency_key` | Bad key | Use UUID |
| 401 | Auth failure | Bad key | Fix server credentials |
| 402 | Payment required | Low balance | Top up |
| 409 | `idempotency_*` | Idempotency conflict | See table above |
| 429 | Rate limit | Too fast | Honor `Retry-After` |
| 5xx | Server error | — | Keep Idempotency-Key; do not blindly rotate |
Prefer `error.message` for UI. Do not surface raw auth internals to end users.
## Differences from 1.5 (summary)
| Item | Grok Imagine 1.5 | 2.0 Ext |
| -------------- | -------------------------------- | ------------------------------------------------ |
| Model | `grok-imagine-1.5-apimart`, etc. | `grok-imagine-2.0-ext` |
| Image-to-image | Supported (see 1.5 docs) | **Not supported** |
| Count | See 1.5 docs | **1–12** |
| Quality field | See 1.5 docs | `resolution` (`quality`); never public `quality` |
| Output | See 1.5 docs | **URL only** |
| URL TTL | See 1.5 docs (often 24h) | **72 hours** |
| Unit price | See 1.5 docs | **\$0.08 / image** |
# Grok Imagine 2.0 Ext Layers and Region Editing
Source: https://docs.apimart.ai/en/api-reference/images/grok-imagine-2.0-ext/layer-region-edit
POST https://api.apimart.ai/v1/images/generations
Use segment to retrieve object layers and precise masks, then edit polygons, boxes, or detected objects with region_edit.
Both `segment` and `region_edit` use the existing asynchronous image endpoint. Save the returned `task_id`, then poll [Get task status](/en/api-reference/tasks/status); the create request does not return final layers or images.
Never expose an API key in a browser bundle, LocalStorage, a URL, or frontend logs. Call APIMart through your backend or BFF.
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Idempotency-Key: 6baf0940-25d6-4ec2-9131-925250840fa7' \
--data '{
"model": "grok-imagine-2.0-ext",
"operation": "segment",
"image_urls": ["https://upload.apimart.ai/f/image/..."],
"cache_only": true,
"include_mask_rle": false
}'
```
```json 200 theme={null}
{
"code": 200,
"data": [{ "status": "submitted", "task_id": "task_..." }]
}
```
## Operation overview
| Purpose | Key input | Completed result | Billing |
| ----------------------------------------------------------------------- | --------------------------------------------------------------- | ---------------------------------- | -------------------------- |
| `segment`: Detect objects and retrieve layers, boxes, and precise masks | `source_task_id`, or `image_urls` containing one uploaded image | `image_id`, `image_url`, `objects` | Free |
| `region_edit`: Edit a polygon, rectangle, or detected object | `image_id`, `prompt`, selection | New URL and `image_id` | Charged per completed task |
```text theme={null}
completed task_id ───────┐
├→ segment → image_id + mask_rle
uploaded public image URL┘ → selection_regions → region_edit → new task_id + image_id
```
Choose exactly one `segment` source: `source_task_id` or `image_urls`. These fields and `image_id` are not interchangeable; `region_edit` still takes the asset ID returned by `segment`. To segment an edited image, use the completed `region_edit` task ID as the next `source_task_id`.
## Request headers
Use `Authorization: Bearer `, `Content-Type: application/json`, and `Accept: application/json`.
`Idempotency-Key` is optional and strongly recommended for paid `region_edit` requests. It accepts 1–191 visible ASCII characters; UUID is recommended. Use a new key for each new logical operation. A network retry of the same request must reuse the original key and identical body. If a paid edit has an indeterminate result, do not retry automatically with a new key.
## Asynchronous task flow
A successful create request returns HTTP `200` and `data[0].task_id`. Poll `GET /v1/tasks/{task_id}?language=en` every 2 seconds, back off to at most 5 seconds, and set a 10-minute overall timeout. Stop old polling when the source image changes.
A task query can return HTTP `200` while `data.status` is `failed`. Always determine success from `data.status` and display `data.error` when present.
## `segment`
### Request parameters
| Field | Type | Required | Description |
| ------------------ | --------- | :---------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model` | string | ✅ | Fixed to `grok-imagine-2.0-ext` |
| `operation` | string | ✅ | Fixed to `segment` |
| `nsfw_check` | boolean | — | Default: `false`.
`true`: use `omni-moderation-latest` to review the source image.
`false` or omitted: do not send a moderation request. |
| `source_task_id` | string | Conditional | A completed, single-image Grok task owned by the current user; mutually exclusive with `image_urls` |
| `image_urls` | string\[] | Conditional | Exactly one publicly accessible absolute HTTP(S) URL; mutually exclusive with `source_task_id`. Upload local images with `POST /v1/uploads/images`, then use the returned `url` |
| `include_mask_rle` | boolean | — | Default: `true`; `false` omits RLE masks but still returns the asset ID, object indexes, and boxes |
| `cache_only` | boolean | — | Default: `false`; required as `true` with `image_urls`; check segmentation cache only and do not call upstream on a miss |
| `cached_only` | boolean | — | Default: `false`; source-task-only upstream cache hint, not a local cache guarantee |
| `refresh` | boolean | — | Default: `false`; source-task-only cache bypass; do not use in the normal editor flow |
`segment` does not need `prompt`. Do not send `image_id`, `image_index`, `billing_model_name`, `n`, `size`, or `response_format`. Send exactly one of `source_task_id` and `image_urls`. Image URL mode requires `cache_only=true` and does not support `cached_only` or `refresh`.
### Request examples
```json theme={null}
{
"model": "grok-imagine-2.0-ext",
"operation": "segment",
"source_task_id": "",
"include_mask_rle": true,
"cached_only": false
}
```
```json theme={null}
{
"model": "grok-imagine-2.0-ext",
"operation": "segment",
"image_urls": ["https://upload.apimart.ai/f/image/..."],
"cache_only": true,
"include_mask_rle": false
}
```
```json theme={null}
{
"model": "grok-imagine-2.0-ext",
"operation": "segment",
"source_task_id": "",
"include_mask_rle": true,
"cache_only": true
}
```
A cache miss is still a successful task. Use `cache_status` (`hit` or `miss`) or `from_cache`; do not infer a hit from `cached`.
### Upload a local image
Upload the local file first and read the public URL from the response:
```bash theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/uploads/images \
--header 'Authorization: Bearer ' \
--form 'file=@/path/to/source.png'
```
Pass the returned `url` as the only item in `image_urls`. Polling, the completed response, and `region_edit` then work exactly as with a task ID: read `result.image_id` and `objects`, then submit the selection edit. Uploaded URLs are temporary and retained for 72 hours by default.
`image_urls` accepts exactly one publicly accessible absolute HTTP(S) URL. Image URL mode supports only `cache_only=true`; do not also send `source_task_id`, `cached_only`, or `refresh`.
### Completed response
For `segment`, `data.result` is the segmentation result directly; it is not wrapped in `images`.
```json theme={null}
{
"code": 200,
"data": {
"id": "task_...",
"status": "completed",
"progress": 100,
"cost": 0,
"credits_cost": 0,
"result": {
"source_task_id": "task_...",
"image_id": "6b78a7c3-5f9e-4a3d-a928-9e9b42113a3f",
"image_url": "https://.../source.jpg",
"from_cache": true,
"cache_status": "hit",
"objects": [{
"index": 0,
"name": "red sports car",
"box_xyxy": [38.1, 689.8, 945.8, 1065.4],
"score": 0.9765625,
"mask_size": [1792, 1008],
"mask_url": "",
"mask_rle": { "size": [1792, 1008], "counts": "..." }
}]
}
}
}
```
| Field | Description |
| --------------------- | -------------------------------------------------------------- |
| `result.image_id` | Asset ID used by `region_edit` |
| `result.image_url` | HTTP(S) URL aligned with `image_id` |
| `objects[].index` | Original server index; preserve it when using `object_indices` |
| `objects[].box_xyxy` | Mask pixel box `[x1,y1,x2,y2]` |
| `objects[].score` | Detection confidence; may be `null` |
| `objects[].mask_size` | Always `[height,width]`; never hard-code dimensions |
| `objects[].mask_rle` | COCO compressed RLE for precise outlines |
| `objects[].mask_url` | Optional mask image URL; may be empty |
An object without a valid `mask_rle` or `mask_url` can only use approximate box editing.
## Decode `mask_rle`
`mask_rle.counts` is a COCO compressed-count string, not Base64 or zlib. It expands in column-major order; the first run is background, followed by alternating foreground and background runs.
The following TypeScript converts it into a browser-friendly row-major binary mask:
```ts theme={null}
export interface CocoRLE {
size: [height: number, width: number];
counts: string;
}
export interface BinaryMask {
width: number;
height: number;
data: Uint8Array; // data[y * width + x]
}
function decodeCompressedCounts(counts: string): number[] {
const runs: number[] = [];
let cursor = 0;
while (cursor < counts.length) {
let value = 0;
let shift = 0;
let more = true;
while (more) {
if (cursor >= counts.length) throw new Error("Truncated COCO RLE counts");
const current = counts.charCodeAt(cursor++) - 48;
value |= (current & 0x1f) << shift;
more = (current & 0x20) !== 0;
shift += 5;
if (!more && (current & 0x10) !== 0) value |= -1 << shift;
}
if (runs.length > 2) value += runs[runs.length - 2] ?? 0;
if (value < 0) throw new Error(\`Invalid COCO RLE run: \${value}\`);
runs.push(value);
}
return runs;
}
export function decodeCocoRLE(rle: CocoRLE): BinaryMask {
const [height, width] = rle.size;
if (!Number.isInteger(height) || !Number.isInteger(width) || height <= 0 || width <= 0) {
throw new Error(\`Invalid mask size: \${JSON.stringify(rle.size)}\`);
}
const pixelCount = width * height;
if (!Number.isSafeInteger(pixelCount) || pixelCount > 32_000_000) {
throw new Error(\`Mask exceeds the frontend safety limit: \${pixelCount}\`);
}
if (!rle.counts) throw new Error("Missing COCO RLE counts");
const data = new Uint8Array(pixelCount);
const runs = decodeCompressedCounts(rle.counts);
let position = 0;
let foreground = false;
for (const run of runs) {
if (position + run > data.length) throw new Error("COCO RLE exceeds mask_size");
if (foreground) {
for (let offset = 0; offset < run; offset++) {
const index = position + offset;
const y = index % height;
const x = (index - y) / height;
data[y * width + x] = 1;
}
}
position += run;
foreground = !foreground;
}
if (position !== data.length) throw new Error("COCO RLE does not cover the mask");
return { width, height, data };
}
```
Decode large masks in a Web Worker. Never send complete `mask_rle.counts` values to logs, analytics, URLs, or error reporting.
### Convert masks to precise selections
```ts theme={null}
interface SelectionBoundary { points: number[] }
interface SelectionRegion { outer: SelectionBoundary; holes?: SelectionBoundary[] }
```
Trace connected components and holes, simplify the contours, and normalize every point to `0–1`. Each ring needs at least 3 distinct points, must have non-zero area, and must not self-intersect. Keep at most 16 largest regions per layer and 400 points per ring.
`mask_size` is `[height,width]` and uses source-mask coordinates, not CSS display coordinates. With `object-fit: contain`, subtract letterbox offsets, scale against the actual drawn area, and clamp the final values to `0–1`.
Reading source-image or `mask_url` pixels requires CORS. Set `crossOrigin = "anonymous"` before `src`, or fetch a Blob. Decoding `mask_rle` directly avoids this dependency.
## Edit a region: `region_edit`
### Request parameters
| Field | Type | Required | Description |
| ------------------- | ------------ | :------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model` | string | ✅ | Fixed to `grok-imagine-2.0-ext` |
| `operation` | string | ✅ | `region_edit` |
| `nsfw_check` | boolean | — | Default: `false`.
`true`: use `omni-moderation-latest` to review the edit prompt and input image.
`false` or omitted: do not send a moderation request. |
| `image_id` | string | ✅ | Source asset ID; first use `segment` result `image_id`, then use the latest edit result |
| `prompt` | string | ✅ | Non-empty instruction describing the desired change |
| `selection_regions` | array | \* | Normalized `0–1` polygons with `outer` and optional `holes`; recommended |
| `boxes` | number\[]\[] | \* | Rectangles `[x1,y1,x2,y2]`; pixel boxes require `mask_size` |
| `object_indices` | integer\[] | \* | Original `objects[].index` values; approximate box editing only |
| `mask_size` | integer\[] | \* | Required for pixel boxes; `[height,width]` with positive integers |
At least one of `selection_regions`, `boxes`, or `object_indices` must be non-empty. The API accepts combinations, but the frontend should use one method per request.
Do not send `billing_model_name`, `size`, `aspect_ratio`, `source_aspect_ratio`, `source_size`, or `image_urls`. Omit `n` or set it to `1`; omit `claim_asset` or set it to `false`; omit `response_format` or set it to `url`. Base64 output and `stream=true` are unsupported.
### Selection methods
| Method | Selection source | Precision | Recommended use |
| ------------------- | ------------------------ | ---------------------- | --------------------------------- |
| `selection_regions` | Frontend polygons | Exact, including holes | Production layer or brush editing |
| `boxes` | Frontend rectangles | Box approximation | Box tool or MVP |
| `object_indices` | Original segment indices | Box approximation | Quick integration testing |
```json theme={null}
{
"model": "grok-imagine-2.0-ext",
"operation": "region_edit",
"image_id": "",
"prompt": "Change the selected car to bright red and preserve the rest",
"selection_regions": [{
"outer": { "points": [0.12, 0.20, 0.48, 0.20, 0.48, 0.61, 0.12, 0.61] },
"holes": [{ "points": [0.30, 0.35, 0.38, 0.35, 0.38, 0.45, 0.30, 0.45] }]
}]
}
```
`points` can be flat or nested pairs. Every value must be finite and within `0–1`; each ring needs at least 3 coordinate pairs.
```json theme={null}
{
"model": "grok-imagine-2.0-ext",
"operation": "region_edit",
"image_id": "",
"prompt": "Change the car inside the box to bright red",
"boxes": [[0.04, 0.385, 0.938, 0.594]]
}
```
```json theme={null}
{
"model": "grok-imagine-2.0-ext",
"operation": "region_edit",
"image_id": "",
"prompt": "Change the car inside the box to bright red",
"boxes": [[40, 689.6, 945.9, 1064.4]],
"mask_size": [1792, 1008]
}
```
```json theme={null}
{
"model": "grok-imagine-2.0-ext",
"operation": "region_edit",
"image_id": "",
"prompt": "Change the selected car to bright red",
"object_indices": [0]
}
```
Indices must come from the segment response for the same `image_id`. Do not replace them with indices from a filtered, sorted, or grouped frontend array.
### Completed response
```json theme={null}
{
"code": 200,
"data": {
"id": "task_...",
"status": "completed",
"progress": 100,
"cost": 0.016,
"credits_cost": 0.16,
"result": {
"images": [{
"url": ["https://.../result.jpg"],
"image_ids": [""],
"items": [{
"url": "https://.../result.jpg",
"image_id": "",
"source_image_id": "",
"role": "region_edit"
}],
"expires_at": 1787040000
}]
}
}
}
```
Prefer `result.images[0].items[0]`. For legacy responses, pair `url[0]` with `image_ids[0]` only when the arrays have equal lengths. Continue only after obtaining both an HTTP(S) URL and a new `image_id`.
Use `expires_at` as the source of truth for URL expiry; do not hard-code a number of hours. Download or persist assets needed for long-term display.
## Continuous editing
After an edit completes, update the displayed URL, the current asset ID, and the source task ID together, then clear old layers and polling state.
* Segment again: use this `region_edit` task ID as `source_task_id`
* Edit again: use the newly returned `image_id`
* Never pass `image_id` to `segment`, and never keep editing the previous image ID.
## Error handling
| HTTP / status | Common cause | Handling |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| 400 invalid source or operation | Wrong operation; both or neither source supplied; unusable task; invalid image URL; or `image_id/image_index` sent to segment | Choose exactly one valid source. For uploads, send one public HTTP(S) URL with `cache_only=true` |
| 400 invalid selection | Empty prompt, missing selection, invalid polygon, box, or object index | Validate the prompt and selection before submission |
| 400 unsupported option | Invalid `claim_asset`, `n`, output format, size, or stream mode | Remove unsupported fields and use URL output |
| 401 / 403 | Invalid key or missing model permission | Check the server-side key and account access |
| 402 | Insufficient balance for a paid edit | Ask the user to top up before retrying |
| 409 | Idempotency request is in progress, changed, or indeterminate | Follow the response; do not switch keys automatically |
| 429 / 5xx | Rate limit or temporary service failure | Honor `Retry-After` and retry with bounded backoff |
| failed / task\_failed | Asynchronous execution failed | Stop polling and show `data.error.message` |
## Billing
* `segment` is free and completes with `cost=0` and `credits_cost=0`, but still requires authentication and a valid source input.
* `region_edit` is paid. Use the completed task's `cost` and `credits_cost`; do not hard-code prices in the frontend.
* Never send the internal field `billing_model_name`.
## Frontend checklist
* Keep the API key only in the backend or BFF.
* Send one `segment` source: `source_task_id`, or `image_urls` containing one public URL. Do not send `image_id` or `image_index`.
* With `image_urls`, set `cache_only=true` and omit `cached_only` and `refresh`.
* Use segment's `image_id` for `region_edit` and provide at least one selection method.
* Use `selection_regions` for precise production editing; `object_indices` is only a box approximation.
* Always parse `mask_size` as `[height,width]` and account for display scaling and letterboxing.
* Reuse the original idempotency key for the same network retry and validate both the output URL and new `image_id`.
# Grok Imagine Image 2.0 Official Generation and Editing
Source: https://docs.apimart.ai/en/api-reference/images/grok-imagine-2.0-ext/official
POST https://api.apimart.ai/v1/images/generations
Asynchronous image generation and editing with grok-imagine-image-2.0
This is an **asynchronous image endpoint**. A successful submission returns a task ID. Poll [Get Task Status](/en/api-reference/tasks/status) for the final result. Omit `image_urls` for text-to-image; include them for image editing or multi-image reference.
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'X-APIMart-Response-Version: 2026-07-27' \
--data '{
"model": "grok-imagine-image-2.0",
"prompt": "A cinematic neon-lit city street in the rain",
"n": 1,
"aspect_ratio": "16:9",
"resolution": "2k",
"quality": "medium"
}'
```
```json 202 theme={null}
{
"code": 202,
"request_id": "req_xxx",
"data": {
"id": "task_01KZQE5CM0Y3KZ6M1N1BK619MX",
"object": "generation.task",
"type": "image",
"status": "pending",
"progress": 0,
"poll_url": "/v1/tasks/task_01KZQE5CM0Y3KZ6M1N1BK619MX"
}
}
```
## Model capabilities
| Model | Resolution | `quality` | Input images | Outputs |
| ------------------------ | ---------- | ---------------------------------------- | -----------: | ------: |
| `grok-imagine-image-2.0` | `1k`, `2k` | `low` or `medium` for text-to-image only | 0–3 | 1–10 |
## Authorization
Use `Bearer YOUR_API_KEY`.
## Body
Must be `grok-imagine-image-2.0`.
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Image generation or editing instructions. Must be non-empty after trimming and no longer than 8,000 characters.
Number of output images, from `1` to `10`.
Supported values: `1:1`, `3:4`, `4:3`, `9:16`, `16:9`, `2:3`, `3:2`, `9:19.5`, `19.5:9`, `9:20`, `20:9`, `1:2`, `2:1`, and `auto`.
`1k` or `2k`.
Text-to-image only: `low` or `medium` (default). Do not send this field when `image_urls` is present.
One to three reference images. Only publicly accessible absolute HTTP(S) URLs are accepted. Upload local images with `POST /v1/uploads/images`, then use the returned `url`. Omit the field when there is no reference image.
## Asynchronous task flow
The submission response uses HTTP `202`; the task ID is in `data.id`. Use `data.poll_url` or `GET /v1/tasks/{task_id}` until the task becomes `completed` or `failed`. See [Get Task Status](/en/api-reference/tasks/status).
Do not expose a long-lived APIMart API key in browser code, public environment variables, URLs, local storage, or client logs. Call this endpoint from your backend or BFF.
# Grok Imagine Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/grok-imagine/generation
POST https://api.apimart.ai/v1/images/generations
- Async processing mode, returns task ID for subsequent queries
- Supports text-to-image and reference-based image editing
- Also documents the grok-imagine-image and grok-imagine-image-quality models
- Generated image links are valid for 24 hours; please save them promptly
**Model name compatibility note**: This endpoint also accepts the alias `grok-imagine-1.5-ext`, which is equivalent to `grok-imagine-1.5-apimart`. The two are interchangeable and produce identical results.
```bash cURL theme={null}
# model can be "grok-imagine-1.5-apimart", or the compatible alias "grok-imagine-1.5-ext"
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "grok-imagine-1.5-apimart",
"prompt": "An orange cat sitting on a sunny windowsill, oil painting style",
"size": "1:1",
"n": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "grok-imagine-1.5-apimart",
"prompt": "An orange cat sitting on a sunny windowsill, oil painting style",
"size": "1:1",
"n": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "grok-imagine-1.5-apimart",
prompt: "An orange cat sitting on a sunny windowsill, oil painting style",
size: "1:1",
n: 1
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "grok-imagine-1.5-apimart",
"prompt": "An orange cat sitting on a sunny windowsill, oil painting style",
"size": "1:1",
"n": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "grok-imagine-1.5-apimart",
"prompt": "An orange cat sitting on a sunny windowsill, oil painting style",
"size": "1:1",
"n": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"grok-imagine-1.5-apimart",
"prompt" => "An orange cat sitting on a sunny windowsill, oil painting style",
"size" => "1:1",
"n" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "grok-imagine-1.5-apimart",
prompt: "An orange cat sitting on a sunny windowsill, oil painting style",
size: "1:1",
n: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "grok-imagine-1.5-apimart",
"prompt": "An orange cat sitting on a sunny windowsill, oil painting style",
"size": "1:1",
"n": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""grok-imagine-1.5-apimart"",
""prompt"": ""An orange cat sitting on a sunny windowsill, oil painting style"",
""size"": ""1:1"",
""n"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/images/generations";
const char *payload = "{"
"\"model\":\"grok-imagine-1.5-apimart\","
"\"prompt\":\"An orange cat sitting on a sunny windowsill, oil painting style\","
"\"size\":\"1:1\","
"\"n\":1"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/images/generations"];
NSDictionary *payload = @{
@"model": @"grok-imagine-1.5-apimart",
@"prompt": @"An orange cat sitting on a sunny windowsill, oil painting style",
@"size": @"1:1",
@"n": @1
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/images/generations"
let payload = {|{
"model": "grok-imagine-1.5-apimart",
"prompt": "An orange cat sitting on a sunny windowsill, oil painting style",
"size": "1:1",
"n": 1
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'grok-imagine-1.5-apimart',
'prompt': 'An orange cat sitting on a sunny windowsill, oil painting style',
'size': '1:1',
'n': 1
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json'
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "grok-imagine-1.5-apimart",
prompt = "An orange cat sitting on a sunny windowsill, oil painting style",
size = "1:1",
n = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JNXXXXXXXXXXXXXXXXXX"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway, server temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All APIs require Bearer Token authentication
Get API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
Supported models:
* `grok-imagine-1.5-apimart` - Grok image generation and editing (compatible alias `grok-imagine-1.5-ext`)
Example: `"grok-imagine-1.5-ext"`
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation or editing, supports multiple languages
Reference image URL list. **Omit for text-to-image; include for image editing**.
* This model supports 1–5 reference images
* Only publicly accessible absolute `http://` or `https://` URLs are accepted
* Upload local images with `POST /v1/uploads/images`, then use the returned `url`
Output image size
Supported formats:
* `1:1` - Square (default)
* `16:9` - Landscape widescreen
* `9:16` - Portrait tall
* `3:2` - Landscape
* `2:3` - Portrait
Number of images to generate
Range: 1-10 (minimum 1, maximum 10)
**⚠️ Note:** Must be a plain number (e.g. `1`), do not add quotes, otherwise an error will occur
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
## Use Cases
### Case 1: Text-to-Image
```json theme={null}
{
"model": "grok-imagine-1.5-apimart",
"prompt": "An orange cat sitting on a sunny windowsill, oil painting style"
}
```
### Case 2: Text-to-Image (size & count)
```json theme={null}
{
"model": "grok-imagine-1.5-apimart",
"prompt": "A starry night sky background with a person standing in the foreground",
"size": "16:9",
"n": 2
}
```
### Case 3: Image Editing (background)
```json theme={null}
{
"model": "grok-imagine-1.5-apimart",
"prompt": "Change the background to a starry sky, keep the main subject",
"image_urls": ["https://example.com/original.png"]
}
```
### Case 4: Image Editing (style)
```json theme={null}
{
"model": "grok-imagine-1.5-apimart",
"prompt": "Convert the image to cyberpunk style",
"image_urls": ["https://example.com/original.png"],
"n": 2
}
```
## Official Models
`grok-imagine-image` and `grok-imagine-image-quality` use the same asynchronous task flow as other image models. A successful submission returns a task ID; poll [Get Task Status](/en/api-reference/tasks/status) until the task completes or fails.
| Model | Resolution | Quality option | Input images | Outputs |
| ---------------------------- | ---------- | -------------- | -----------: | ------: |
| `grok-imagine-image` | `1k`, `2k` | None | 0–5 | 1–10 |
| `grok-imagine-image-quality` | `1k`, `2k` | None | 0–3 | 1–10 |
Do not send `quality` for either model. Omit `image_urls` for text-to-image; one image performs single-image editing; multiple images provide multi-image references.
### Request parameters
| Field | Type | Required | Description |
| -------------- | --------- | :------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model` | string | Yes | `grok-imagine-image` or `grok-imagine-image-quality` |
| `nsfw_check` | boolean | No | Default: `false`.
`true`: use `omni-moderation-latest` to review prompts and input images.
`false` or omitted: do not send a moderation request. |
| `prompt` | string | Yes | Non-empty after trimming; maximum 8,000 characters |
| `n` | integer | No | Default: `1`; allowed values: `1`–`10` |
| `aspect_ratio` | string | No | Default: `auto`; use a supported aspect ratio or `auto` |
| `resolution` | string | No | Default: `1k`; allowed values: `1k` or `2k` |
| `image_urls` | string\[] | No | 1–5 images for `grok-imagine-image`; 1–3 for `grok-imagine-image-quality` |
Supported `aspect_ratio` values: `1:1`, `3:4`, `4:3`, `9:16`, `16:9`, `2:3`, `3:2`, `9:19.5`, `19.5:9`, `9:20`, `20:9`, `1:2`, `2:1`, and `auto`.
```bash theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'X-APIMart-Response-Version: 2026-07-27' \
--data '{
"model": "grok-imagine-image",
"prompt": "Minimal product photography of a white ceramic cup",
"n": 1,
"aspect_ratio": "1:1",
"resolution": "2k"
}'
```
### Task submission response
```json 202 theme={null}
{
"code": 202,
"data": {
"id": "task_01KZQE5CM0Y3KZ6M1N1BK619MX",
"object": "generation.task",
"type": "image",
"status": "pending",
"progress": 0,
"poll_url": "/v1/tasks/task_01KZQE5CM0Y3KZ6M1N1BK619MX"
}
}
```
Use `data.id` or `data.poll_url` to query the task until its status becomes `completed` or `failed`.
# Imagen 4.0 Apimart Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/imagen-4.0-apimart/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Based on Google Imagen 4 model, high-quality image generation
- Only supports text-to-image, does not support image-to-image / reference images
- Supported ratios: 16:9 (landscape), 9:16 (portrait)
- Generated image links are valid for 24 hours, please save them promptly
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "imagen-4.0-apimart",
"prompt": "A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
"size": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "imagen-4.0-apimart",
"prompt": "A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
"size": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "imagen-4.0-apimart",
prompt: "A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
size: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "imagen-4.0-apimart",
"prompt": "A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
"size": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "imagen-4.0-apimart",
"prompt": "A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
"size": "16:9"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"imagen-4.0-apimart",
"prompt" => "A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
"size" => "16:9"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "imagen-4.0-apimart",
prompt: "A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
size: "16:9"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "imagen-4.0-apimart",
"prompt": "A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
"size": "16:9"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""imagen-4.0-apimart"",
""prompt"": ""A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k"",
""size"": ""16:9""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/images/generations";
const char *payload = "{"
"\"model\":\"imagen-4.0-apimart\","
"\"prompt\":\"A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k\","
"\"size\":\"16:9\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/images/generations"];
NSDictionary *payload = @{
@"model": @"imagen-4.0-apimart",
@"prompt": @"A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
@"size": @"16:9"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/images/generations"
let payload = {|{
"model": "imagen-4.0-apimart",
"prompt": "A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
"size": "16:9"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'imagen-4.0-apimart',
'prompt': 'A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k',
'size': '16:9'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json'
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "imagen-4.0-apimart",
prompt = "A corgi wearing an astronaut helmet, standing on the lunar surface, Earth in the background, cinematic lighting, 8k",
size = "16:9"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8AYYM6R03TGZ3Q2P0TZVNPX"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "google_imagen4 currently supports text-to-image only",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, server temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All APIs require Bearer Token authentication
Get API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to obtain your API Key
Add the following to your request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
Fixed value: `imagen-4.0-apimart`
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
Both English and Chinese descriptions are supported
Number of images to generate
Value range: 1
Image generation ratio
Supported formats:
* `1:1` - Square
* `4:3` - Landscape
* `3:4` - Portrait
* `16:9` - Landscape (default)
* `9:16` - Portrait
Ratios not in the supported list (e.g. `21:9`) will automatically fall back to the default `16:9` without raising an error.
Unsupported fields: `image`, `image_urls`, `mask`, `quality`, etc. will be ignored. If `image_urls` / `image` is passed, it will error directly: `google_imagen4 currently supports text-to-image only`.
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier for querying task results
# Best Practices
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/best-practices
Polling patterns, prompt design, image guidance, error-retry strategies, concurrency, and troubleshooting tips for Midjourney integration
Consolidated best practices for common questions, performance tuning, and error handling. **Recommended reading before you integrate.**
## Task submission and polling
Submission endpoints are all asynchronous tasks: after submitting they return a `task_id`, then you periodically query `GET /v1/midjourney/{task_id}` for the status until `SUCCESS` / `FAILURE`.
```python theme={null}
import time, httpx
def wait_task(task_id, timeout=300):
deadline = time.time() + timeout
while time.time() < deadline:
resp = httpx.get(f"{HOST}/v1/midjourney/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"}).json()
if resp["status"] in ("SUCCESS", "FAILURE"):
return resp
if resp["status"] == "MODAL":
raise RuntimeError(f"task {task_id} needs a /modal call to supply params and complete")
time.sleep(3)
raise TimeoutError(task_id)
```
* **Polling cadence**: 3–5s is recommended; higher frequency is pointless and wastes quota.
* **Do not block synchronously in a web request** waiting for the task to finish — return the `task_id` immediately after submitting and let the frontend poll asynchronously.
## Prompt design
**A good prompt:**
```text theme={null}
a serene mountain lake at sunrise, photorealistic, soft golden light,
mist rising from water, snow-capped peaks in distance --ar 16:9 --v 8.1 --s 100
```
* **Subject first**: lead with the subject, then describe the scene, and put modifiers last.
* **Make structured params explicit**: using `--ar` / `--v` / `--s` (or the corresponding body fields) is more controllable than relying on defaults.
* **Avoid ambiguous words**: `photorealistic` is clearer than `realistic`.
**Avoid:** being overly abstract ("make it good"), scattered subjects (multiple parallel objects with no clear priority), and quoting words (they are treated as literal values).
**Niji anime:** pass `niji: true` + `version: "7"`; the platform normalizes it to `--niji 7`, and billing goes through `midjourney@imagine-niji7`.
## Image-guidance best practices
| Source | Recommended approach | Notes |
| --------------------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------- |
| User upload | Store it in your own OSS / CDN first, then pass that URL on submit | Do not pass base64 directly (wastes bandwidth) |
| Public URL | Pass it directly | Watch out for SSRF (must be publicly reachable) and the 12 MiB limit |
| Third-party / other outputs | Re-host to your own OSS first | Third-party URLs may expire |
* **Compress to \< 5 MiB**: the platform limit is 12 MiB, but smaller images transfer / process faster.
* PNG / JPG / WebP are all fine; high-quality JPG is recommended.
* A resolution of 1024–2048 px is already enough; higher is wasteful.
* Image weight `iw` (0–3, default 1): >1 stays closer to the source image, \<1 is more free.
## Error handling and retry strategy
| code | Meaning | Retry strategy |
| --------------------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `1` / `200` | Success | ✅ |
| `4` VALIDATION\_ERROR | Bad parameters | ❌ Do not retry; fix the parameters |
| `3` NOT\_FOUND | No available instance / task\_id does not exist | If the instance is unavailable you can retry later; do not retry if the task\_id does not exist |
| `9` FAILURE | Service rejection / internal error | ⏳ Retryable, exponential backoff (1s, 4s, 16s) |
| `21` MODAL | Non-terminal state | ✅ Keep calling `/modal` |
| `24` BANNED\_PROMPT | Sensitive word | ❌ Do not retry; change the prompt; **already auto-refunded** |
| `429` | Rate limited | ⏳ Exponential backoff + jitter |
| `5xx` / network error | Server / network | ⏳ Exponential backoff; for network errors you may retry once immediately |
```python theme={null}
import time, random, httpx
def submit_with_retry(payload, max_attempts=5):
for attempt in range(max_attempts):
try:
r = httpx.post(f"{HOST}/v1/midjourney/generations/imagine",
json=payload,
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=30)
data = r.json()
if r.status_code == 200 and data["code"] in (1, 200):
return data
if data["code"] in (4, 24):
raise ValueError(data["description"]) # not retryable
if data["code"] == 3 and "task" in data["description"]:
raise ValueError(data["description"]) # task_id does not exist
# the rest (9 / 429 / 5xx) are retryable
except httpx.RequestError:
pass
time.sleep((4 ** attempt) + random.uniform(0, 1)) # 1s / 4s / 16s ...
raise RuntimeError(f"reached max retry count {max_attempts}")
```
## Follow-up operation flow
```python theme={null}
# imagine → poll → upscale
imagine_id = submit({"prompt": "a cat"})["data"][0]["task_id"]
result = wait_task(imagine_id) # grid_image_url + 4 image_urls + buttons
upscale_id = submit_to("/upscale", {"task_id": imagine_id, "index": 2})["data"][0]["task_id"]
final = wait_task(upscale_id) # upscale is composed locally, 1–2s
single_image = final["image_urls"][0]
```
Inpaint (two-step inpaint → modal):
```python theme={null}
imagine_id = submit({"prompt": "a portrait"})["data"][0]["task_id"]; wait_task(imagine_id)
upscale_id = submit_to("/upscale", {"task_id": imagine_id, "index": 1})["data"][0]["task_id"]; wait_task(upscale_id)
inpaint_id = submit_to("/inpaint", {"task_id": upscale_id})["data"][0]["task_id"] # status=modal
# Frontend draws the mask (transparent = repaint area), uploads it to your own OSS to get mask_url
final = submit_to("/modal", {
"task_id": inpaint_id,
"prompt": "replace the eyes with cybernetic blue eyes",
"mask_url": "https://your-oss.com/mask.png"
})
wait_task(final["data"][0]["task_id"])
```
> ⚠️ After inpaint enters MODAL you must call `/modal` **within 30 minutes**, otherwise the backend auto-cancels (CANCEL) and refunds.
## Video billing control
* Single segment: `batch_size: 1` → charged 1 × `midjourney@video`
* Batch of 4 segments: `batch_size: 4` → charged 4 × `midjourney@video`
* HD single segment: `video_type: "vid_1.1_i2v_720"` + `batch_size: 1` → charged 1 × `midjourney@video-720p`
**Recommendation**: if you only need 1 segment for delivery, use `batch_size=1`; only use 4 for batch comparison drafts. Do not default to 4 (it multiplies cost N times).
## Concurrency and throughput
```python theme={null}
import asyncio
sem = asyncio.Semaphore(10) # client submits at most 10 concurrently
async def submit_one(prompt):
async with sem:
return await submit({"prompt": prompt})
```
* The platform has a per-minute submission cap; exceeding it returns `429`, which needs backoff retry.
* Actual generation concurrency is determined by system capacity; exceeding it queues; a task staying in `SUBMITTED` for a long time usually means it is queued.
* Always include `sleep` when polling; do not spin in a tight loop without sleep.
## Monitoring recommendations
| Metric | Reference threshold | Meaning |
| ------------------------------ | ------------------- | --------------------------------------------------------------- |
| Task SUCCESS rate (last 1h) | > 95% | Low values indicate service / network issues |
| Average completion time | \< 90s | High values indicate queuing |
| Number of tasks stuck in MODAL | Near 0 | Many indicate the client did not call `/modal` |
| Proportion of `code=24` | \< 5% | High values indicate prompts frequently trigger sensitive words |
## Troubleshooting checklist
| Symptom | Where to look |
| ----------------------------------------- | -------------------------------------------------------------------------------- |
| Task stuck in `SUBMITTED` for a long time | Queued in the system; check again later |
| Task stuck in `NOT_START` for a long time | The platform will auto-timeout and refund later; no manual action needed |
| Task in `MODAL` over 30 minutes | The client did not call `/modal`; it has been auto-cancelled (CANCEL) + refunded |
| `prompt` field is empty | The text result of a describe task is in the `description` field |
| Missing one image in `image_urls` | Content moderation blocked part of the images; check `fail_reason` |
| Billing higher than expected | Check the `quota` field; for video remember to multiply by `batch_size` |
# Blend (multi-image blend)
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/blend
POST https://api.apimart.ai/v1/midjourney/generations/blend
Blend 2–4 images into a new image (the classic MJ blend); image-only, no prompt supported
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/blend \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"image_urls": [
"https://example.com/a.png",
"https://example.com/b.png"
],
"dimensions": "SQUARE",
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/blend"
payload = {
"image_urls": [
"https://example.com/a.png",
"https://example.com/b.png"
],
"dimensions": "SQUARE",
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/blend";
const payload = {
image_urls: [
"https://example.com/a.png",
"https://example.com/b.png"
],
dimensions: "SQUARE",
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/blend"
payload := map[string]interface{}{
"image_urls": []string{
"https://example.com/a.png",
"https://example.com/b.png",
},
"dimensions": "SQUARE",
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/blend";
String payload = """
{
"image_urls": [
"https://example.com/a.png",
"https://example.com/b.png"
],
"dimensions": "SQUARE",
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
[
"https://example.com/a.png",
"https://example.com/b.png",
],
"dimensions" => "SQUARE",
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/blend")
payload = {
image_urls: [
"https://example.com/a.png",
"https://example.com/b.png",
],
dimensions: "SQUARE",
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/blend")!
let payload: [String: Any] = [
"image_urls": [
"https://example.com/a.png",
"https://example.com/b.png",
],
"dimensions": "SQUARE",
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/blend";
var payload = @"{
""image_urls"": [
""https://example.com/a.png"",
""https://example.com/b.png""
],
""dimensions"": ""SQUARE"",
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/blend";
const char *payload = "{"
"\"image_urls\":[\"https://example.com/a.png\",\"https://example.com/b.png\"],"
"\"dimensions\":\"SQUARE\","
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/blend"];
NSDictionary *payload = @{
@"image_urls": @[
@"https://example.com/a.png",
@"https://example.com/b.png",
],
@"dimensions": @"SQUARE",
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/blend"
let payload = {|{
"image_urls": [
"https://example.com/a.png",
"https://example.com/b.png"
],
"dimensions": "SQUARE",
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/blend');
final payload = {
'image_urls': [
'https://example.com/a.png',
'https://example.com/b.png',
],
'dimensions': 'SQUARE',
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/blend"
payload <- list(
image_urls = list(
"https://example.com/a.png",
"https://example.com/b.png"
),
dimensions = "SQUARE",
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Image or prompt failed content moderation; automatically refunded",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Blend 2–4 images into a new image (the classic MJ blend feature). It works purely from images and **does not accept a prompt**.
| Item | Value |
| -------- | -------------------------- |
| action | `BLEND` |
| Billing | `midjourney@blend[-speed]` |
| Required | `image_urls` (2–4 images) |
## Parameters
| Field | Type | Required | Notes |
| ------------ | --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image_urls` | string\[] | Yes | Source images, 2–4; auto-converted to base64; each ≤ 12 MiB |
| `nsfw_check` | boolean | No | Defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `dimensions` | string | No | Default: `SQUARE`; Three aspect presets: `SQUARE` (1:1) / `PORTRAIT` (2:3) / `LANDSCAPE` (3:2); overridden when `size` is set |
| `size` | string | No | Free aspect ratio, any `w:h` (e.g. `"16:9"`, `"9:16"`, `"21:9"`); **takes priority over `dimensions`**, applied as the aspect ratio |
| `speed` | string | No | Default: `relax`; `relax` / `fast` / `turbo` |
| `metadata` | object | No | Custom metadata |
## Request examples
Preset aspect (`dimensions`):
```json theme={null}
{
"image_urls": [
"https://example.com/a.png",
"https://example.com/b.png"
],
"dimensions": "SQUARE",
"speed": "fast"
}
```
Free aspect (`size`):
```json theme={null}
{
"image_urls": [
"https://example.com/a.png",
"https://example.com/b.png"
],
"size": "16:9",
"speed": "fast"
}
```
> The final prompt ends with `--ar 16:9`.
## Notes
* Aspect priority: `size` (free) > `dimensions` (presets) > default `SQUARE`.
* Fewer than 2 or more than 4 `image_urls` returns `400`.
* `blend` has no independent version parameter. To price by speed, configure `midjourney@blend-fast` / `midjourney@blend-turbo`.
# Describe (image to text)
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/describe
POST https://api.apimart.ai/v1/midjourney/generations/describe
Reverse a prompt from an image; responds synchronously (1–3s), result in the prompt / description fields
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/describe \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"image_urls": [
"https://example.com/input.png"
],
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/describe"
payload = {
"image_urls": [
"https://example.com/input.png"
],
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/describe";
const payload = {
image_urls: [
"https://example.com/input.png"
],
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/describe"
payload := map[string]interface{}{
"image_urls": []string{
"https://example.com/input.png",
},
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/describe";
String payload = """
{
"image_urls": [
"https://example.com/input.png"
],
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
[
"https://example.com/input.png",
],
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/describe")
payload = {
image_urls: [
"https://example.com/input.png",
],
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/describe")!
let payload: [String: Any] = [
"image_urls": [
"https://example.com/input.png",
],
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/describe";
var payload = @"{
""image_urls"": [
""https://example.com/input.png""
],
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/describe";
const char *payload = "{"
"\"image_urls\":[\"https://example.com/input.png\"],"
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/describe"];
NSDictionary *payload = @{
@"image_urls": @[
@"https://example.com/input.png",
],
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/describe"
let payload = {|{
"image_urls": [
"https://example.com/input.png"
],
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/describe');
final payload = {
'image_urls': [
'https://example.com/input.png',
],
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/describe"
payload <- list(
image_urls = list(
"https://example.com/input.png"
),
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Image or prompt failed content moderation; automatically refunded",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Reverse a prompt from an image. Responds synchronously (measured 1–3s), but it **still follows the platform's standard async flow** — poll the task after submitting.
| Item | Value |
| -------- | ----------------------------- |
| action | `DESCRIBE` |
| Billing | `midjourney@describe[-speed]` |
| Required | `image_urls` (1 image) |
## Parameters
| Field | Type | Required | Notes |
| ------------ | --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image_urls` | string\[] | Yes | A single image; array form, only the first is used; ≤ 12 MiB |
| `nsfw_check` | boolean | No | Defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `speed` | string | No | Default: `relax`; `relax` / `fast` / `turbo` |
| `metadata` | object | No | Custom metadata |
## Request example
```json theme={null}
{
"image_urls": ["https://example.com/input.png"],
"speed": "fast"
}
```
## Response
The text result is in `prompt` / `description` of the query result; **`image_urls` / `grid_image_url` are not returned**. The result is four numbered suggestions, separated by `\n` and prefixed with the digit emoji `1️⃣2️⃣3️⃣4️⃣`:
```json theme={null}
{
"id": "task_xxx",
"status": "SUCCESS",
"action": "DESCRIBE",
"mode": "DESCRIBE",
"prompt": "1️⃣ a serene mountain lake at sunrise --ar 3:2\n2️⃣ mountain landscape with reflections --v 6.1\n3️⃣ panoramic view of alpine lake --ar 16:9\n4️⃣ dawn light over still water --s 250",
"description": "1️⃣ a serene mountain lake at sunrise --ar 3:2\n..."
}
```
## Notes
* Describe runs on an independent processing channel and does not consume the regular image-generation concurrency quota.
* Returns synchronously in \~1–3s, but you still poll `GET /v1/tasks/{task_id}` (or `GET /v1/midjourney/{task_id}`) for the result.
* A missing image returns `400`; a single image over 12 MiB returns `400`.
# Edits (image edit)
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/edits
POST https://api.apimart.ai/v1/midjourney/generations/edits
Rewrite the whole image from an existing image + prompt. Good for background replacement, style transfer, content changes
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/edits \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
"image_urls": [
"https://example.com/product.png"
],
"version": "8.1",
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/edits"
payload = {
"prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
"image_urls": [
"https://example.com/product.png"
],
"version": "8.1",
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/edits";
const payload = {
prompt: "replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
image_urls: [
"https://example.com/product.png"
],
version: "8.1",
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/edits"
payload := map[string]interface{}{
"prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
"image_urls": []string{
"https://example.com/product.png",
},
"version": "8.1",
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/edits";
String payload = """
{
"prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
"image_urls": [
"https://example.com/product.png"
],
"version": "8.1",
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
"image_urls" => [
"https://example.com/product.png",
],
"version" => "8.1",
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/edits")
payload = {
prompt: "replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
image_urls: [
"https://example.com/product.png",
],
version: "8.1",
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/edits")!
let payload: [String: Any] = [
"prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
"image_urls": [
"https://example.com/product.png",
],
"version": "8.1",
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/edits";
var payload = @"{
""prompt"": ""replace the background with a modern kitchen, keep the product unchanged --ar 1:1"",
""image_urls"": [
""https://example.com/product.png""
],
""version"": ""8.1"",
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/edits";
const char *payload = "{"
"\"prompt\":\"replace the background with a modern kitchen, keep the product unchanged --ar 1:1\","
"\"image_urls\":[\"https://example.com/product.png\"],"
"\"version\":\"8.1\","
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/edits"];
NSDictionary *payload = @{
@"prompt": @"replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
@"image_urls": @[
@"https://example.com/product.png",
],
@"version": @"8.1",
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/edits"
let payload = {|{
"prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
"image_urls": [
"https://example.com/product.png"
],
"version": "8.1",
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/edits');
final payload = {
'prompt': 'replace the background with a modern kitchen, keep the product unchanged --ar 1:1',
'image_urls': [
'https://example.com/product.png',
],
'version': '8.1',
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/edits"
payload <- list(
prompt = "replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
image_urls = list(
"https://example.com/product.png"
),
version = "8.1",
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Image or prompt failed content moderation; automatically refunded",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
**Rewrites the whole image** from an existing image + prompt. Good for background replacement, style transfer, and content changes.
| Item | Value |
| -------- | -------------------------- |
| action | `EDITS` |
| Billing | `midjourney@edits[-speed]` |
| Required | `prompt` + `image_urls` |
## Parameters
| Field | Type | Required | Notes |
| ------------ | --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `prompt` | string | Yes | Edit instruction |
| `nsfw_check` | boolean | No | Defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `image_urls` | string\[] | Yes | Image to edit; each ≤ 12 MiB |
| `speed` | string | No | Default: `relax`; `relax` / `fast` / `turbo` |
| `metadata` | object | No | Custom metadata |
### Structured fields (optional)
Same as [Imagine](./imagine) — set them in the body or in `prompt` (e.g. `--ar 16:9`). Body values take priority, are appended to the prompt, and override same-name flags written by hand.
| Field | Type | MJ equivalent | Notes |
| ----------------- | ------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `size` | string | `--ar` | e.g. `"16:9"`, `"1:1"`, `"9:16"` |
| `quality` | string | `--q` | `"0.25"`, `"0.5"`, `"1"`, `"2"` |
| `style` | string | `--style` | e.g. `"raw"` |
| `version` | string | `--v` | Version. Main MJ versions append `--v `; when used with `niji: true` and `"7"` / `"6"`, it is normalized as a Niji version |
| `seed` | int | `--seed` | Seed |
| `negative_prompt` | string | `--no` | e.g. `"ugly, blurry"` |
| `stylize` | int | `--s` | 0–1000 |
| `chaos` | int | `--c` | 0–100 |
| `weird` | int | `--w` | 0–3000 |
| `tile` | bool | `--tile` | Tile mode |
| `niji` | bool | `--niji` | Niji switch. Recommended: `niji: true` + `version: "7"` / `"6"` |
| `iw` | float | `--iw` | 0–3, image weight |
| `cw` | int | `--cw` | 0–100 |
| `sw` | int | `--sw` | 0–1000 |
| `cref` | string | `--cref` | Character ref URL |
| `sref` | string | `--sref` | Style ref URL |
| `dref` | string | `--dref` | Depth reference image URL |
| `dw` | float | `--dw` | Depth weight (0–100) |
| `repeat` | int | `--repeat` | 2–40 |
| `raw` | bool | `--raw` | Raw style (v5.1+) |
| `draft` | bool | `--draft` | Draft mode (v7+) |
| `hd` | bool | `--hd` | HD mode (v8.1 / v8.2 only; backend auto-injects `--v 8.1` when `version` is unspecified) |
| `stop` | int | `--stop` | Early stop (10–100; v5–6.1 / niji 5–6 only) |
| `extra` | string | any `--xxx` | Escape hatch; appended to prompt verbatim |
## Request example
```json theme={null}
{
"prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1",
"image_urls": ["https://example.com/product.png"],
"version": "8.1",
"speed": "fast"
}
```
## Response
Submission returns a `task_id`; on SUCCESS the result includes edited `image_urls` (may be 1–4) plus `grid_image_url`.
## Notes
* Difference from imagine image-guidance: edits "rewrites the whole image", while imagine + reference images "borrows the style".
* Missing `prompt` or `image_urls` returns `400`; a single image over 12 MiB returns `400`.
# Midjourney API overview
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/generation
- Overview of Midjourney text-to-image (Imagine) / image-guided / follow-up actions / image-to-video endpoints
- Async task mode: receive task_id after submission, poll for the result
- New routes auto-inject model=midjourney and support native MJ args, structured body fields, and metadata
**Base URL:** `https://api.apimart.ai`
**Auth:** `Authorization: Bearer `
New `/v1/midjourney/...` routes automatically inject `model=midjourney`; you do not need to pass `model` in the request body.
## Quick start
```bash theme={null}
# 1. Submit an Imagine job
curl -X POST https://api.apimart.ai/v1/midjourney/generations \
-H "Authorization: Bearer " \
-H "Content-Type: application/json" \
-d '{"prompt": "a cute cat, watercolor style --ar 16:9"}'
# 2. Poll the unified task API until status=completed
curl https://api.apimart.ai/v1/tasks/task_01JWXXXX \
-H "Authorization: Bearer "
# 3. Upscale image 1
curl -X POST https://api.apimart.ai/v1/midjourney/generations/upscale \
-H "Authorization: Bearer " \
-H "Content-Type: application/json" \
-d '{"task_id": "task_01JWXXXX", "index": 1}'
```
## API overview
See each feature's sub-page for full fields, examples, and notes.
| Feature | Path | Doc |
| ------------------------------ | ---------------------------------------------------------------- | ---------------------------------- |
| Text-to-image (default entry) | `POST /v1/midjourney/generations` | [Imagine](./imagine) |
| Text-to-image (explicit entry) | `POST /v1/midjourney/generations/imagine` | [Imagine](./imagine) |
| Multi-image blend | `POST /v1/midjourney/generations/blend` | [Blend](./blend) |
| Image to text (describe) | `POST /v1/midjourney/generations/describe` | [Describe](./describe) |
| Image edit | `POST /v1/midjourney/generations/edits` | [Edits](./edits) |
| Upscale a tile | `POST /v1/midjourney/generations/upscale` | [Upscale](./upscale) |
| Variation | `POST /v1/midjourney/generations/variation` | [Variation](./variation) |
| High variation | `POST /v1/midjourney/generations/high-variation` | [High Variation](./high-variation) |
| Low variation | `POST /v1/midjourney/generations/low-variation` | [Low Variation](./low-variation) |
| Reroll | `POST /v1/midjourney/generations/reroll` | [Reroll](./reroll) |
| Zoom out | `POST /v1/midjourney/generations/zoom` | [Zoom](./zoom) |
| Pan | `POST /v1/midjourney/generations/pan` | [Pan](./pan) |
| Inpaint | `POST /v1/midjourney/generations/inpaint` | [Inpaint](./inpaint) |
| Modal parameters | `POST /v1/midjourney/generations/modal` | [Modal](./modal) |
| Image-to-video | `POST /v1/midjourney/generations/video` | [Video](./video) |
| Remix (strong / subtle) | `POST /v1/midjourney/generations/remix-strong` · `/remix-subtle` | [Remix](./remix) |
| Task query | `GET /v1/tasks/{task_id}` · `/v1/midjourney/{task_id}` | [Get task](./query) |
See also: [Best practices](./best-practices) (polling / retries / troubleshooting) · [End-to-end workflows](./workflow) (curl walkthroughs + client wrappers)
## End-to-end flow
```mermaid theme={null}
flowchart TB
A["① POST /generations
submit Imagine"] --> B["② GET /v1/tasks/{task_id}
poll until completed"]
B --> C["③ If buttons are needed
GET /v1/midjourney/{task_id}"]
C --> D1["/upscale"]
C --> D2["/variation"]
C --> D3["/reroll"]
C --> D4["/zoom"]
C --> D5["/inpaint
(enters MODAL)"]
D5 --> M["/modal
submit mask + prompt"]
```
## Errors
### Error response format
```json theme={null}
{
"error": {
"type": "invalid_request_error",
"message": "prompt is required"
}
}
```
### Common errors
| HTTP | type | Meaning |
| ---- | ----------------------- | ----------------------------------------------------- |
| 400 | `invalid_request_error` | Bad parameters (missing required, wrong format, etc.) |
| 401 | `authentication_error` | Invalid API key |
| 402 | `payment_required` | Insufficient balance |
| 404 | `not_found` | Task not found |
| 429 | `rate_limit_error` | Rate limited |
| 500 | `internal_error` | Server error |
### Task failures
Common `fail_reason` values:
* `Banned prompt detected` — banned prompt content
* `Task timeout` — task timeout (auto refund after 30+ minutes)
* `No available upstream` — service temporarily unavailable, retry later
## Billing
The unified model name for new MJ routes is `midjourney`. Billing keys are generated from action, version, and speed. The usual match order is:
```text theme={null}
midjourney@--
-> midjourney@-
-> midjourney@-
-> midjourney@
-> midjourney
```
| Action | Bill name | Notes |
| -------------- | --------------------------------------------- | -------------------------------------- |
| Imagine | `midjourney@imagine[-version][-speed]` | Text-to-image / image-guided |
| Blend | `midjourney@blend[-speed]` | Multi-image blend |
| Describe | `midjourney@describe[-speed]` | Image to text |
| Edits | `midjourney@edits[-speed]` | Image edit |
| Upscale | `midjourney@upscale[-version][-speed]` | Upscale |
| Variation | `midjourney@variation[-version][-speed]` | Variation |
| High Variation | `midjourney@high_variation[-version][-speed]` | Strong variation |
| Low Variation | `midjourney@low_variation[-version][-speed]` | Subtle variation |
| Reroll | `midjourney@reroll[-version][-speed]` | Regenerate |
| Zoom | `midjourney@zoom[-version][-speed]` | Zoom out / outpaint |
| Pan | `midjourney@pan[-version][-speed]` | Pan outpaint |
| Inpaint | `midjourney@inpaint[-version][-speed]` | Inpaint entry |
| Modal | `midjourney@modal[-speed]` | Inpaint follow-up parameters |
| Video | `midjourney@video` / `midjourney@video-720p` | Image-to-video, charged × `batch_size` |
| Remix Strong | `midjourney@remix_strong[-speed]` | Strong reshape (v8.1 / v8.2 only) |
| Remix Subtle | `midjourney@remix_subtle[-speed]` | Subtle reshape (v8.1 / v8.2 only) |
Notes:
* `speed=relax` or omitted `speed` does not add a speed suffix; `fast` / `turbo` add the corresponding suffix.
* Main versions normalize to `v8.2`, `v8.1`, `v7`, `v6.1`, `v5.2`, and `v5.1`.
* `niji=true + version=7/6` normalizes to `niji7` / `niji6`.
> See console pricing. Failed jobs are fully refunded.
# High Variation
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/high-variation
POST https://api.apimart.ai/v1/midjourney/generations/high-variation
Strong variation (varyStrong, Vary (Strong)) on a single upscaled image
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/high-variation \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/high-variation"
payload = {
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/high-variation";
const payload = {
task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
index: 1,
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/high-variation"
payload := map[string]interface{}{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/high-variation";
String payload = """
{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index" => 1,
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/high-variation")
payload = {
task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
index: 1,
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/high-variation")!
let payload: [String: Any] = [
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/high-variation";
var payload = @"{
""task_id"": ""task_01KQW0D3WJ2QYJP9E3H7GZ4D2R"",
""index"": 1,
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/high-variation";
const char *payload = "{"
"\"task_id\":\"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R\","
"\"index\":1,"
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/high-variation"];
NSDictionary *payload = @{
@"task_id": @"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
@"index": @1,
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/high-variation"
let payload = {|{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/high-variation');
final payload = {
'task_id': 'task_01KQW0D3WJ2QYJP9E3H7GZ4D2R',
'index': 1,
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/high-variation"
payload <- list(
task_id = "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
index = 1,
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Strong variation (varyStrong, Vary (Strong); larger change, deviates more from the original) on a single image after Upscale. For a subtle variation see [Variation](./variation).
| Item | Value |
| -------- | ----------------------------------------------- |
| action | `HIGH_VARIATION` |
| Billing | `midjourney@high_variation[-speed]` |
| Required | `task_id` + `index`, or `task_id` + `custom_id` |
| Optional | `speed`, `metadata` |
## Parameters
| Field | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `task_id` | Task ID returned by this platform (typically the Upscale single-image task) |
| `nsfw_check` | `boolean` — Optional; defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `index` | `1`–`4`; Required when `custom_id` is omitted; button matching does not use `index` |
| `custom_id` | Button ID for the corresponding action; when set, skips `index` auto-matching |
| `speed` | `relax` / `fast` / `turbo` |
| `metadata` | Optional custom metadata |
## Auto matching
Prefer `Vary (Strong)`, then fall back to `Make Variations`.
## Request example
```json theme={null}
{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast"
}
```
## Notes
* Typically call `upscale` on the Imagine grid first, then call this endpoint with the new `task_id` returned by Upscale.
* In the current implementation, when `custom_id` is omitted, `index` is still required even though button matching does not use `index`.
* Version metadata from the source task is inherited automatically. To price by speed, configure `midjourney@high_variation-fast` / `midjourney@high_variation-turbo`.
## Response
On success you receive a new local `task_id`. Poll `GET /v1/tasks/{task_id}` for the result.
# Imagine (text-to-image)
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/imagine
POST https://api.apimart.ai/v1/midjourney/generations
Midjourney text-to-image / image-guided generation. The default entry /v1/midjourney/generations and the explicit /imagine entry behave the same
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"prompt": "a beautiful sunset over mountains",
"size": "16:9",
"version": "6.1",
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations"
payload = {
"prompt": "a beautiful sunset over mountains",
"size": "16:9",
"version": "6.1",
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations";
const payload = {
prompt: "a beautiful sunset over mountains",
size: "16:9",
version: "6.1",
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations"
payload := map[string]interface{}{
"prompt": "a beautiful sunset over mountains",
"size": "16:9",
"version": "6.1",
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations";
String payload = """
{
"prompt": "a beautiful sunset over mountains",
"size": "16:9",
"version": "6.1",
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"a beautiful sunset over mountains",
"size" => "16:9",
"version" => "6.1",
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations")
payload = {
prompt: "a beautiful sunset over mountains",
size: "16:9",
version: "6.1",
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations")!
let payload: [String: Any] = [
"prompt": "a beautiful sunset over mountains",
"size": "16:9",
"version": "6.1",
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations";
var payload = @"{
""prompt"": ""a beautiful sunset over mountains"",
""size"": ""16:9"",
""version"": ""6.1"",
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations";
const char *payload = "{"
"\"prompt\":\"a beautiful sunset over mountains\","
"\"size\":\"16:9\","
"\"version\":\"6.1\","
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations"];
NSDictionary *payload = @{
@"prompt": @"a beautiful sunset over mountains",
@"size": @"16:9",
@"version": @"6.1",
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations"
let payload = {|{
"prompt": "a beautiful sunset over mountains",
"size": "16:9",
"version": "6.1",
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations');
final payload = {
'prompt': 'a beautiful sunset over mountains',
'size': '16:9',
'version': '6.1',
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations"
payload <- list(
prompt = "a beautiful sunset over mountains",
size = "16:9",
version = "6.1",
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Image or prompt failed content moderation; automatically refunded",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Default text-to-image / image-guided endpoint, equivalent to `imagine`. The explicit `/v1/midjourney/generations/imagine` endpoint behaves the same way.
| Item | Value |
| -------- | ------------------------------------------------ |
| action | `IMAGINE` |
| Billing | `midjourney@imagine[-version][-speed]` |
| Required | `prompt` |
| Optional | `image_urls`, prompt fields, `speed`, `metadata` |
## Request body
| Field | Type | Required | Notes |
| ------------ | --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `prompt` | string | Yes | Prompt; native MJ flags allowed (e.g. `--ar 16:9 --v 6.1`) |
| `nsfw_check` | boolean | No | Defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `speed` | string | No | `relax` (default) / `fast` / `turbo` |
| `image_urls` | string\[] | No | Image URLs or base64 for image-guided generation |
| `metadata` | object | No | Custom metadata saved with the task for business-side tracking |
### Structured fields (optional)
You can set these in the JSON body or in `prompt` (e.g. `--ar 16:9`). **Body values override prompt.**
| Field | Type | MJ equivalent | Notes |
| ----------------- | ------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `size` | string | `--ar` | e.g. `"16:9"`, `"1:1"`, `"9:16"` |
| `quality` | string | `--q` | `"0.25"`, `"0.5"`, `"1"`, `"2"` |
| `style` | string | `--style` | e.g. `"raw"` |
| `version` | string | `--v` | Version. Main MJ versions append `--v `; when used with `niji: true` and `"7"` / `"6"`, it is normalized as a Niji version |
| `seed` | int | `--seed` | Seed |
| `negative_prompt` | string | `--no` | e.g. `"ugly, blurry"` |
| `stylize` | int | `--s` | 0–1000 |
| `chaos` | int | `--c` | 0–100 |
| `weird` | int | `--w` | 0–3000 |
| `tile` | bool | `--tile` | Tile mode |
| `niji` | bool | `--niji` | Niji switch. Recommended: `niji: true` + `version: "7"` / `"6"` |
| `iw` | float | `--iw` | 0–3, image weight |
| `cw` | int | `--cw` | 0–100 |
| `sw` | int | `--sw` | 0–1000 |
| `cref` | string | `--cref` | Character ref URL |
| `sref` | string | `--sref` | Style ref URL |
| `dref` | string | `--dref` | Depth reference image URL |
| `dw` | float | `--dw` | Depth weight (0–100) |
| `repeat` | int | `--repeat` | 2–40 |
| `raw` | bool | `--raw` | Raw style (v5.1+) |
| `draft` | bool | `--draft` | Draft mode (v7+) |
| `hd` | bool | `--hd` | HD mode (v8.1 / v8.2 only; backend auto-injects `--v 8.1` when `version` is unspecified) |
| `stop` | int | `--stop` | Early stop (10–100; v5–6.1 / niji 5–6 only) |
| `extra` | string | any `--xxx` | Escape hatch; appended to prompt verbatim |
## Examples
**All flags in prompt**
```json theme={null}
{
"prompt": "a beautiful sunset over mountains --ar 16:9 --v 6.1 --style raw --s 750"
}
```
**Structured body (recommended)**
```json theme={null}
{
"prompt": "a beautiful sunset over mountains",
"size": "16:9",
"version": "6.1",
"style": "raw",
"stylize": 750
}
```
**Main versions and Niji versions**
```json theme={null}
{
"prompt": "anime girl in a moonlit garden",
"niji": true,
"version": "7",
"size": "9:16"
}
```
> Verified online versions: `8.2`, `8.1`, `7`, `6.1`, `5.2`, `5.1`, `niji 7`, and `niji 6`. Use body field `version` for main MJ versions. For Niji, use `niji: true` + `version: "7"` / `"6"`; the billing version is normalized to `niji7` / `niji6`.
**Mixed (body wins)**
```json theme={null}
{
"prompt": "a beautiful sunset --ar 1:1",
"size": "16:9"
}
```
> Final prompt: `a beautiful sunset --ar 16:9` (`size` in body overrides `--ar 1:1` in prompt.)
**Image-guided**
```json theme={null}
{
"prompt": "turn this product into a luxury studio photo",
"image_urls": ["https://example.com/product.png"],
"size": "1:1",
"iw": 1.2
}
```
**Fast mode**
```json theme={null}
{
"prompt": "a cute cat",
"speed": "fast"
}
```
> `speed=relax` or omitted `speed` does not add a billing speed suffix. `fast` / `turbo` are applied through the corresponding speed routes and match the corresponding billing keys.
## Response
```json theme={null}
{
"code": 200,
"data": [{
"status": "submitted",
"task_id": "task_01JWXXXXXXXXXXXX"
}]
}
```
After submission, poll the result via [Get task](./query).
# Inpaint
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/inpaint
POST https://api.apimart.ai/v1/midjourney/generations/inpaint
Region inpaint entry (Vary (Region)); after submission the task enters MODAL, then call modal with mask + prompt
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/inpaint \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/inpaint"
payload = {
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/inpaint";
const payload = {
task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/inpaint"
payload := map[string]interface{}{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/inpaint";
String payload = """
{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/inpaint")
payload = {
task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/inpaint")!
let payload: [String: Any] = [
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/inpaint";
var payload = @"{
""task_id"": ""task_01KQW0D3WJ2QYJP9E3H7GZ4D2R"",
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/inpaint";
const char *payload = "{"
"\"task_id\":\"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R\","
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/inpaint"];
NSDictionary *payload = @{
@"task_id": @"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/inpaint"
let payload = {|{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/inpaint');
final payload = {
'task_id': 'task_01KQW0D3WJ2QYJP9E3H7GZ4D2R',
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/inpaint"
payload <- list(
task_id = "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Image or prompt failed content moderation; automatically refunded",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Entry point for region inpaint (equivalent to `Vary (Region)`). **After submission the task enters the `MODAL` state**; you must then call [modal](./modal) with a mask + prompt to finish.
| Item | Value |
| -------- | -------------------------------------- |
| action | `INPAINT` |
| Billing | `midjourney@inpaint[-version][-speed]` |
| Required | `task_id`, or `task_id` + `custom_id` |
| Optional | `index`, `speed`, `metadata` |
## Parameters
| Field | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `task_id` | Source task ID (typically an Upscale single-image task) |
| `nsfw_check` | `boolean` — Optional; defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `custom_id` | Optional; button ID for the corresponding `Vary (Region)` action |
| `index` | Optional; which image of the parent task (`1`–`4`, default `1`); usually unnecessary for a single image |
| `speed` | `relax` / `fast` / `turbo` |
| `metadata` | Optional custom metadata |
## Auto matching
The service matches `Vary (Region)` from the source task `buttons`.
## Request example
```json theme={null}
{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"speed": "fast"
}
```
## Follow-up
On success the response returns `status: "modal"` — this is a **valid non-terminal state, not an error**. Continue with the [modal](./modal) endpoint, where **`task_id` is the local task ID returned by inpaint**, plus **`prompt`** and optional **`mask_url`**.
```json theme={null}
{
"task_id": "task_03_inpaint...",
"status": "modal",
"model": "midjourney"
}
```
## Notes
* The parent task must be a **SUCCESS upscaled single image**; inpainting a grid directly errors — call `upscale` first.
* After entering MODAL you must **call modal within 30 minutes**, otherwise the backend auto-cancels and refunds.
* Version metadata from the source task is inherited automatically. To price by speed, configure `midjourney@inpaint-fast` / `midjourney@inpaint-turbo`.
# Low Variation
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/low-variation
POST https://api.apimart.ai/v1/midjourney/generations/low-variation
Subtle variation (varySubtle, same behavior as Variation, only the billing key differs) on a single upscaled image
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/low-variation \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/low-variation"
payload = {
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/low-variation";
const payload = {
task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
index: 1,
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/low-variation"
payload := map[string]interface{}{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/low-variation";
String payload = """
{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index" => 1,
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/low-variation")
payload = {
task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
index: 1,
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/low-variation")!
let payload: [String: Any] = [
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/low-variation";
var payload = @"{
""task_id"": ""task_01KQW0D3WJ2QYJP9E3H7GZ4D2R"",
""index"": 1,
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/low-variation";
const char *payload = "{"
"\"task_id\":\"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R\","
"\"index\":1,"
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/low-variation"];
NSDictionary *payload = @{
@"task_id": @"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
@"index": @1,
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/low-variation"
let payload = {|{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/low-variation');
final payload = {
'task_id': 'task_01KQW0D3WJ2QYJP9E3H7GZ4D2R',
'index': 1,
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/low-variation"
payload <- list(
task_id = "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
index = 1,
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Subtle variation (varySubtle, behaves identically to Variation) on a single image after Upscale. The separate endpoint exists mainly for naming consistency (the dual of [High Variation](./high-variation)) and independent pricing; new integrations should use [Variation](./variation) directly.
| Item | Value |
| -------- | ----------------------------------------------- |
| action | `LOW_VARIATION` |
| Billing | `midjourney@low_variation[-speed]` |
| Required | `task_id` + `index`, or `task_id` + `custom_id` |
| Optional | `speed`, `metadata` |
## Parameters
| Field | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `task_id` | Task ID returned by this platform (typically the Upscale single-image task) |
| `nsfw_check` | `boolean` — Optional; defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `index` | `1`–`4`; Required when `custom_id` is omitted; button matching does not use `index` |
| `custom_id` | Button ID for the corresponding action; when set, skips `index` auto-matching |
| `speed` | `relax` / `fast` / `turbo` |
| `metadata` | Optional custom metadata |
## Auto matching
Prefer `Vary (Subtle)`, then fall back to `Make Variations`.
## Request example
```json theme={null}
{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"index": 1,
"speed": "fast"
}
```
## Notes
* Typically call `upscale` on the Imagine grid first, then call this endpoint with the new `task_id` returned by Upscale.
* In the current implementation, when `custom_id` is omitted, `index` is still required even though button matching does not use `index`.
* Version metadata from the source task is inherited automatically. To price by speed, configure `midjourney@low_variation-fast` / `midjourney@low_variation-turbo`.
## Response
On success you receive a new local `task_id`. Poll `GET /v1/tasks/{task_id}` for the result.
# Modal (submit parameters)
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/modal
POST https://api.apimart.ai/v1/midjourney/generations/modal
Supply mask + prompt to complete a MODAL-state inpaint task
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/modal \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C",
"prompt": "replace the selected area with a red leather sofa",
"mask_url": "https://example.com/mask.png",
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/modal"
payload = {
"task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C",
"prompt": "replace the selected area with a red leather sofa",
"mask_url": "https://example.com/mask.png",
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/modal";
const payload = {
task_id: "task_01KQW1N9T6E3AHW6QZFDEK8M5C",
prompt: "replace the selected area with a red leather sofa",
mask_url: "https://example.com/mask.png",
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/modal"
payload := map[string]interface{}{
"task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C",
"prompt": "replace the selected area with a red leather sofa",
"mask_url": "https://example.com/mask.png",
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/modal";
String payload = """
{
"task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C",
"prompt": "replace the selected area with a red leather sofa",
"mask_url": "https://example.com/mask.png",
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"task_01KQW1N9T6E3AHW6QZFDEK8M5C",
"prompt" => "replace the selected area with a red leather sofa",
"mask_url" => "https://example.com/mask.png",
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/modal")
payload = {
task_id: "task_01KQW1N9T6E3AHW6QZFDEK8M5C",
prompt: "replace the selected area with a red leather sofa",
mask_url: "https://example.com/mask.png",
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/modal")!
let payload: [String: Any] = [
"task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C",
"prompt": "replace the selected area with a red leather sofa",
"mask_url": "https://example.com/mask.png",
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/modal";
var payload = @"{
""task_id"": ""task_01KQW1N9T6E3AHW6QZFDEK8M5C"",
""prompt"": ""replace the selected area with a red leather sofa"",
""mask_url"": ""https://example.com/mask.png"",
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/modal";
const char *payload = "{"
"\"task_id\":\"task_01KQW1N9T6E3AHW6QZFDEK8M5C\","
"\"prompt\":\"replace the selected area with a red leather sofa\","
"\"mask_url\":\"https://example.com/mask.png\","
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/modal"];
NSDictionary *payload = @{
@"task_id": @"task_01KQW1N9T6E3AHW6QZFDEK8M5C",
@"prompt": @"replace the selected area with a red leather sofa",
@"mask_url": @"https://example.com/mask.png",
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/modal"
let payload = {|{
"task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C",
"prompt": "replace the selected area with a red leather sofa",
"mask_url": "https://example.com/mask.png",
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/modal');
final payload = {
'task_id': 'task_01KQW1N9T6E3AHW6QZFDEK8M5C',
'prompt': 'replace the selected area with a red leather sofa',
'mask_url': 'https://example.com/mask.png',
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/modal"
payload <- list(
task_id = "task_01KQW1N9T6E3AHW6QZFDEK8M5C",
prompt = "replace the selected area with a red leather sofa",
mask_url = "https://example.com/mask.png",
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Image or prompt failed content moderation; automatically refunded",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Complete a MODAL-state inpaint task by supplying a mask + prompt. The system auto-detects the mode by whether `mask_url` is present: **with `mask_url` → inpaint (local repaint); without → outpaint (expand)**.
| Item | Value |
| -------- | ----------------------------------------- |
| action | `MODAL` |
| Billing | `midjourney@modal[-speed]` |
| Required | `task_id` |
| Optional | `prompt`, `mask_url`, `speed`, `metadata` |
## Parameters
| Field | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `task_id` | Local task id returned by the [inpaint](./inpaint) step (must be in MODAL state) |
| `nsfw_check` | `boolean` — Optional; defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `prompt` | Inpaint prompt; if empty, inherits the parent task's prompt |
| `mask_url` | Mask image URL or base64; **required for inpaint (local repaint)**. Transparent = the area to repaint, white = keep the original |
| `speed` | `relax` / `fast` / `turbo` |
| `metadata` | Optional custom metadata |
## Mask requirements
| Item | Recommendation |
| ---------------- | -------------------------------------------------------------------------- |
| Format | PNG with transparent background (also accepts `data:image/png;base64,...`) |
| Resolution | Preferably same as the parent image (the system also auto-resizes) |
| Transparent area | The area to repaint; white areas keep the original |
| Size | ≤ 12 MiB per image |
| URL | Must be publicly reachable (private addresses are blocked by SSRF) |
## Request example
```json theme={null}
{
"task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C",
"prompt": "replace the selected area with a red leather sofa",
"mask_url": "https://example.com/mask.png",
"speed": "fast"
}
```
## Response
The `task_id` stays the same (same task); its status goes from `MODAL` → `SUBMITTED`. Poll `GET /v1/tasks/{task_id}`; on SUCCESS `image_urls` holds 4 inpaint candidates. Billing settles on this endpoint's SUCCESS and is not double-charged with the inpaint step.
To price by speed, configure `midjourney@modal-fast` / `midjourney@modal-turbo`.
# Pan
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/pan
POST https://api.apimart.ai/v1/midjourney/generations/pan
Pan out in a direction on a single upscaled image; chain pans to stitch a panorama (v6 / v6.1 / v7 / v8.1 / v8.2 / niji 6 only)
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/pan \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"direction": "right",
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/pan"
payload = {
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"direction": "right",
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/pan";
const payload = {
task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
direction: "right",
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/pan"
payload := map[string]interface{}{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"direction": "right",
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/pan";
String payload = """
{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"direction": "right",
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"direction" => "right",
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/pan")
payload = {
task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
direction: "right",
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/pan")!
let payload: [String: Any] = [
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"direction": "right",
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/pan";
var payload = @"{
""task_id"": ""task_01KQW0D3WJ2QYJP9E3H7GZ4D2R"",
""direction"": ""right"",
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/pan";
const char *payload = "{"
"\"task_id\":\"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R\","
"\"direction\":\"right\","
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/pan"];
NSDictionary *payload = @{
@"task_id": @"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
@"direction": @"right",
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/pan"
let payload = {|{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"direction": "right",
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/pan');
final payload = {
'task_id': 'task_01KQW0D3WJ2QYJP9E3H7GZ4D2R',
'direction': 'right',
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/pan"
payload <- list(
task_id = "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
direction = "right",
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Pan out in a direction on a single image after Upscale: the original stays at the edge and the new area is filled in. Pan can be chained (keep panning right) to stitch a panorama.
| Item | Value |
| -------- | --------------------------------------------------- |
| action | `PAN` |
| Billing | `midjourney@pan[-speed]` |
| Required | `task_id` + `direction`, or `task_id` + `custom_id` |
| Optional | `index`, `speed`, `metadata` |
## Parameters
| Field | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `task_id` | Task ID returned by this platform (must be an Upscale single-image task) |
| `nsfw_check` | `boolean` — Optional; defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `direction` | `left` / `right` / `up` / `down` |
| `custom_id` | Optional; button ID for the corresponding Pan action; when set, `direction` is not required |
| `index` | Optional (`1`–`4`); backend auto-converts to 0-based |
| `speed` | `relax` / `fast` / `turbo` |
| `metadata` | Optional custom metadata |
Auto matching uses `customId` substrings: `pan_left`, `pan_right`, `pan_up`, and `pan_down`.
## Request example
```json theme={null}
{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"direction": "right",
"speed": "fast"
}
```
## Notes
* **Version support**: pan works only on **v6 / v6.1 / v7 / v8.1 / v8.2 / niji 6**; v5.2 and earlier FAIL (the MJ engine can't run it).
* If it returns `This action requires an upscaled task...`, you passed a grid task; call `upscale` first.
* `direction` must be one of `left` / `right` / `up` / `down`.
* Version metadata from the source task is inherited automatically. To price by speed, configure `midjourney@pan-fast` / `midjourney@pan-turbo`.
## Response
On success you receive a new local `task_id`. Poll `GET /v1/tasks/{task_id}` for the result.
# Get task
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/query
GET https://api.apimart.ai/v1/midjourney/{task_id}
Query Midjourney task status and results. Unified task API /v1/tasks/{task_id} and MJ-style API /v1/midjourney/{task_id}
```bash cURL theme={null}
curl --request GET \
--url https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK \
--header 'Authorization: Bearer '
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK"
headers = {
"Authorization": "Bearer "
}
response = requests.get(url, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK";
const headers = {
"Authorization": "Bearer "
};
fetch(url, {
method: "GET",
headers: headers
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer ")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.GET()
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = "Bearer "
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var response = await client.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"GET"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK"
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
in
let response = Client.get ~headers (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer ',
},
);
print(response.body);
}
```
```r R theme={null}
library(httr)
url <- "https://api.apimart.ai/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK"
response <- GET(
url,
add_headers(
Authorization = "Bearer "
)
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"id": "task_01KV52C0TEJSYZMCG0NCS4YWKK",
"status": "SUCCESS",
"action": "IMAGINE",
"progress": "100%",
"grid_image_url": "https://cdn.apimart.ai/mj_xxxx.png",
"image_urls": [
"https://cdn.apimart.ai/mj_xxxx_0.png",
"https://cdn.apimart.ai/mj_xxxx_1.png",
"https://cdn.apimart.ai/mj_xxxx_2.png",
"https://cdn.apimart.ai/mj_xxxx_3.png"
],
"buttons": [
{"customId": "MJ::JOB::upsample::1::abc123def456", "label": "U1"},
{"customId": "MJ::JOB::variation::1::abc123def456", "label": "V1"}
],
"prompt": "a beautiful sunset over mountains"
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Recommended polling endpoint for the business side:
```
GET /v1/tasks/{task_id}
```
Unified task statuses are `pending` / `processing` / `completed` / `failed`; successful results are returned in `result.images[].url`.
Use the MJ-style endpoint when you need `buttons[].customId` for follow-up actions:
```
GET /v1/midjourney/{task_id}
```
## Status flow
```
SUBMITTED → IN_PROGRESS → SUCCESS
→ FAILURE
→ MODAL (needs extra parameters, see Inpaint)
```
## Response example
```json theme={null}
{
"id": "task_01JWXXXX",
"status": "SUCCESS",
"action": "IMAGINE",
"progress": "100%",
"grid_image_url": "https://cdn.apimart.ai/mj_xxxx.png",
"image_urls": [
"https://cdn.apimart.ai/mj_xxxx_0.png",
"https://cdn.apimart.ai/mj_xxxx_1.png",
"https://cdn.apimart.ai/mj_xxxx_2.png",
"https://cdn.apimart.ai/mj_xxxx_3.png"
],
"buttons": [
{"customId": "MJ::JOB::upsample::1::abc123def456", "label": "U1"},
{"customId": "MJ::JOB::variation::1::abc123def456", "label": "V1"}
],
"prompt": "a beautiful sunset over mountains"
}
```
> `grid_image_url` is the 2x2 grid image; `image_urls` are the four cropped single-image URLs.
**Field naming gotchas**
* `/v1/tasks/{task_id}` returns unified `pending` / `processing` / `completed` / `failed` statuses.
* `/v1/midjourney/{task_id}` returns MJ-style fields such as `grid_image_url`, `image_urls`, and `buttons`.
**About `buttons`:** For most follow-up actions, pass `index`, `direction`, or `zoom_ratio` and the service maps the matching `customId`. If auto matching fails, pass `custom_id` directly.
## Status overview
| status | Meaning | Terminal |
| ------------- | ----------------------------------------------------------------- | -------- |
| `NOT_START` | Row created, not yet confirmed by the system (transient) | No |
| `SUBMITTED` | System accepted, queued | No |
| `IN_PROGRESS` | System processing | No |
| `MODAL` | Waiting for `/modal` parameters (see Inpaint) | No |
| `SUCCESS` | Done | ✓ |
| `FAILURE` | Failed → auto-refund (`quota` → 0, `fail_reason` holds the cause) | ✓ |
## Query notes
* The query endpoint is **not billed separately**, but keep the rate reasonable (3–5s polling recommended).
* A regular user can only query their own tasks; querying others' returns `403`.
* Tasks are retained for **3 days** by default; after that, queries return `404`, but the generated image / video URLs remain accessible.
## Advanced: act directly with custom\_id
After reading `buttons[].customId`, you can pass it directly to the `custom_id` field of a follow-up action endpoint to bypass auto matching:
```json theme={null}
{
"task_id": "task_01JWXXXX",
"custom_id": "MJ::JOB::upsample::1::abc123def456"
}
```
# Remix (reshape, v8.1 / v8.2 only)
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/remix
POST https://api.apimart.ai/v1/midjourney/generations/remix-strong
The v8 panel's reshape: regenerates the parent image and can change the prompt, in strong / subtle strengths
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/remix-strong \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"task_id": "task_",
"index": 1,
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/remix-strong"
payload = {
"task_id": "task_",
"index": 1,
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/remix-strong";
const payload = {
task_id: "task_",
index: 1,
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/remix-strong"
payload := map[string]interface{}{
"task_id": "task_",
"index": 1,
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/remix-strong";
String payload = """
{
"task_id": "task_",
"index": 1,
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"task_",
"index" => 1,
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/remix-strong")
payload = {
task_id: "task_",
index: 1,
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/remix-strong")!
let payload: [String: Any] = [
"task_id": "task_",
"index": 1,
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/remix-strong";
var payload = @"{
""task_id"": ""task_"",
""index"": 1,
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/remix-strong";
const char *payload = "{"
"\"task_id\":\"task_\","
"\"index\":1,"
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/remix-strong"];
NSDictionary *payload = @{
@"task_id": @"task_",
@"index": @1,
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/remix-strong"
let payload = {|{
"task_id": "task_",
"index": 1,
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/remix-strong');
final payload = {
'task_id': 'task_',
'index': 1,
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/remix-strong"
payload <- list(
task_id = "task_",
index = 1,
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Image or prompt failed content moderation; automatically refunded",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
The v8 panel's "reshape" — regenerates the parent image and can change the prompt. **Only available for v8.1 / v8.2 parent tasks**; for v7 / v6 parents use [Variation](./variation) / [High Variation](./high-variation) instead.
```
POST /v1/midjourney/generations/remix-strong
POST /v1/midjourney/generations/remix-subtle
```
> The v8 panel removed U1-U4 / zoom / outpaint / inpaint. Replacements: variation → Variation / High Variation; reshape → this endpoint; regenerate → Reroll.
| Item | Value |
| -------- | --------------------------------------------------------------------- |
| action | `REMIX_STRONG` / `REMIX_SUBTLE` |
| Billing | `midjourney@remix_strong[-speed]` / `midjourney@remix_subtle[-speed]` |
| Required | `task_id` + `index` |
## Parameters
| Field | Type | Required | Notes |
| ------------ | ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `task_id` | string | Yes | Parent task (**v8.1 / v8.2 imagine SUCCESS**) |
| `nsfw_check` | boolean | No | Defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `index` | int | Yes | Which parent tile to reshape (`1`–`4`) |
| `prompt` | string | No | Default: (inherits parent); New prompt for the reshape; if empty, uses the parent's prompt |
| `speed` | string | No | Default: `relax`; `relax` / `fast` / `turbo` |
## Strength comparison
| Endpoint | op | Change amount | Analogy |
| --------------- | ------------- | ------------------------------------------: | ---------------------------- |
| `/remix-strong` | `remixStrong` | Large change, composition / style may shift | Like High Variation (strong) |
| `/remix-subtle` | `remixSubtle` | Small change, keeps subject / tone | Like Variation (subtle) |
## Request example
Strong reshape:
```json theme={null}
{
"task_id": "task_",
"index": 1,
"speed": "fast"
}
```
A custom prompt is passed through and can change the style / add details.
## Response
Submission returns a new local `task_id`; poll `GET /v1/tasks/{task_id}`, and on SUCCESS it includes 4 reshaped images.
## Notes
* **Only v8.1 / v8.2 parents work**; a non-v8 parent returns `400`.
* For v7 / v6 parents use [Variation](./variation) / [High Variation](./high-variation) / [Low Variation](./low-variation).
# Reroll
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/reroll
POST https://api.apimart.ai/v1/midjourney/generations/reroll
Regenerate 4 images from the source task's prompt (🔄). The whole grid is re-rolled, no index needed
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/reroll \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/reroll"
payload = {
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/reroll";
const payload = {
task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK",
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/reroll"
payload := map[string]interface{}{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/reroll";
String payload = """
{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"task_01KQVZAPBW13W63DQNQZT7FCQK",
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/reroll")
payload = {
task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK",
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/reroll")!
let payload: [String: Any] = [
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/reroll";
var payload = @"{
""task_id"": ""task_01KQVZAPBW13W63DQNQZT7FCQK"",
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/reroll";
const char *payload = "{"
"\"task_id\":\"task_01KQVZAPBW13W63DQNQZT7FCQK\","
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/reroll"];
NSDictionary *payload = @{
@"task_id": @"task_01KQVZAPBW13W63DQNQZT7FCQK",
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/reroll"
let payload = {|{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/reroll');
final payload = {
'task_id': 'task_01KQVZAPBW13W63DQNQZT7FCQK',
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/reroll"
payload <- list(
task_id = "task_01KQVZAPBW13W63DQNQZT7FCQK",
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Regenerate 4 images from the source task's prompt (equivalent to the 🔄 button). The whole grid is re-rolled, so **no `index` is needed**.
| Item | Value |
| -------- | ------------------------------------- |
| action | `REROLL` |
| Billing | `midjourney@reroll[-speed]` |
| Required | `task_id`, or `task_id` + `custom_id` |
| Optional | `speed`, `metadata` |
## Parameters
| Field | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `task_id` | Original task ID returned by this platform |
| `nsfw_check` | `boolean` — Optional; defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `custom_id` | Optional; button ID for the corresponding reroll action |
| `speed` | `relax` / `fast` / `turbo` |
| `metadata` | Optional custom metadata |
## Auto matching
The service finds a reroll-related button from the source task `buttons` that contains `::reroll::`, or matches reroll emoji.
## Request example
```json theme={null}
{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"speed": "fast"
}
```
## Error responses
| HTTP | code | description |
| ----- | ---- | ---------------------------------- |
| `400` | 4 | `task_id is required for reroll` |
| `400` | 4 | `task ... is not in SUCCESS state` |
| `404` | 3 | `task ... not found` |
| `502` | 9 | Service rejected |
## Response
On success you receive a new local `task_id`. Poll `GET /v1/tasks/{task_id}`; on SUCCESS you get a **fresh 2x2 grid with the same prompt**.
The source task's prompt / version / niji / structured fields are inherited automatically (the seed may differ, so results differ). To price by speed, configure `midjourney@reroll-fast` / `midjourney@reroll-turbo`.
## Notes
* You can only reroll an imagine grid or a grid produced by reroll itself; **you cannot reroll a task that already went through upscale / variation / pan, etc.**
* The parent task must be in SUCCESS state.
# Upscale
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/upscale
POST https://api.apimart.ai/v1/midjourney/generations/upscale
Pick one of U1–U4 from an Imagine grid to produce a single image; composed locally and usually returns instantly
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/upscale \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 1,
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/upscale"
payload = {
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 1,
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/upscale";
const payload = {
task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK",
index: 1,
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/upscale"
payload := map[string]interface{}{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 1,
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/upscale";
String payload = """
{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 1,
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"task_01KQVZAPBW13W63DQNQZT7FCQK",
"index" => 1,
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/upscale")
payload = {
task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK",
index: 1,
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/upscale")!
let payload: [String: Any] = [
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 1,
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/upscale";
var payload = @"{
""task_id"": ""task_01KQVZAPBW13W63DQNQZT7FCQK"",
""index"": 1,
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/upscale";
const char *payload = "{"
"\"task_id\":\"task_01KQVZAPBW13W63DQNQZT7FCQK\","
"\"index\":1,"
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/upscale"];
NSDictionary *payload = @{
@"task_id": @"task_01KQVZAPBW13W63DQNQZT7FCQK",
@"index": @1,
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/upscale"
let payload = {|{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 1,
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/upscale');
final payload = {
'task_id': 'task_01KQVZAPBW13W63DQNQZT7FCQK',
'index': 1,
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/upscale"
payload <- list(
task_id = "task_01KQVZAPBW13W63DQNQZT7FCQK",
index = 1,
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Picks one of U1–U4 from the parent grid (`grid_image_url`) to produce a single image. This is implemented by **cropping from the existing 4 images**, composed locally and usually returns instantly.
| Item | Value |
| -------- | ----------------------------------------------- |
| action | `UPSCALE` |
| Billing | `midjourney@upscale[-version][-speed]` |
| Required | `task_id` + `index`, or `task_id` + `custom_id` |
| Optional | `speed`, `metadata` |
## Parameters
| Field | Type | Notes |
| ------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `task_id` | string | Parent task ID (must be a SUCCESS imagine / variation / reroll, etc.) |
| `nsfw_check` | boolean | Optional; defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `index` | int | Which tile (U1–U4), range `1`–`4`; one of `index` / `custom_id` |
| `custom_id` | string | Directly pass the button ID for the corresponding action; one of `index` / `custom_id`; when set, `index` matching is skipped |
| `speed` | string | `relax` / `fast` / `turbo` (no effect, since it is composed locally) |
| `metadata` | object | Custom metadata |
## Request examples
By `index`:
```json theme={null}
{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 1,
"speed": "fast"
}
```
Pass a button directly:
```json theme={null}
{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"custom_id": "MJ::JOB::upsample::1::xxxx"
}
```
## Response
Submission returns a new `task_id`, **usually SUCCESS within milliseconds**. On SUCCESS, `image_urls` has a single element (one image), and `buttons` contains follow-up actions (zoom / inpaint / pan / variation, etc.).
## Notes
* The parent task must be in SUCCESS state, otherwise it returns `400` (`task is not in SUCCESS state`).
* `index` must be `1`–`4`; out of range returns `400`. `custom_id` and `index` are mutually exclusive; if both are passed, `custom_id` wins.
* The resource-consuming step is imagine; upscale only picks from existing images and rarely fails.
* The single image after upscale can continue with Zoom / Inpaint / Variation.
## HD upscale (HD enlargement, outputs a single 2x image)
A regular upscale is **composed locally**—it crops one of the 4 images already in the parent task and returns instantly. If you later want to perform fine-grained operations such as zoom / inpaint on a single image, we recommend using **HD upscale** instead: it performs a real enlargement, outputs a **single 2x HD image**, takes about 60–120s to complete, and the resulting single image more reliably supports subsequent zoom / inpaint.
HD upscale specifies the enlargement command via `custom_id`; different imagine versions correspond to different commands:
| customId command | Applicable version |
| ------------------------- | ------------------ |
| `upsample_v5_2x` | v5 imagine |
| `upsample_v5_4x` | v5 imagine |
| `upsample_v6_2x_subtle` | v6 / v6.1 imagine |
| `upsample_v6_2x_creative` | v6 / v6.1 imagine |
| `upsample_v7_2x_subtle` | **v7 imagine** |
| `upsample_v7_2x_creative` | v7 imagine |
### HD upscale example
```json theme={null}
{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"custom_id": "MJ::JOB::upsample_v7_2x_subtle::1::xxxx"
}
```
Once complete, you get a true single 2x HD image task, which you can continue to zoom / inpaint.
### Comparison with regular upscale
| Dimension | Regular upscale | HD upscale |
| -------------- | --------------------------- | ---------------------------- |
| Implementation | Composed locally (cropping) | Real enlargement processing |
| Time | Millisecond-level | About 60–120s |
| Output | Picks the Nth of 4 images | **Single 2x HD image** |
| Follow-up | zoom / inpaint / variation | zoom / inpaint more reliable |
### ⚠️ pan is still unavailable
Even for the HD single image produced by HD upscale, **pan operations are still rejected** (returns "invalid image generation request")—this is a Midjourney limitation on the pan operation itself, unrelated to the enlargement method. See [Pan](./pan) for details.
# Variation
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/variation
POST https://api.apimart.ai/v1/midjourney/generations/variation
Subtle variation (varySubtle, equivalent to V1–V4) on one tile of an Imagine grid
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/variation \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 3,
"speed": "turbo"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/variation"
payload = {
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 3,
"speed": "turbo"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/variation";
const payload = {
task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK",
index: 3,
speed: "turbo"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/variation"
payload := map[string]interface{}{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 3,
"speed": "turbo",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/variation";
String payload = """
{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 3,
"speed": "turbo"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"task_01KQVZAPBW13W63DQNQZT7FCQK",
"index" => 3,
"speed" => "turbo",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/variation")
payload = {
task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK",
index: 3,
speed: "turbo",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/variation")!
let payload: [String: Any] = [
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 3,
"speed": "turbo",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/variation";
var payload = @"{
""task_id"": ""task_01KQVZAPBW13W63DQNQZT7FCQK"",
""index"": 3,
""speed"": ""turbo""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/variation";
const char *payload = "{"
"\"task_id\":\"task_01KQVZAPBW13W63DQNQZT7FCQK\","
"\"index\":3,"
"\"speed\":\"turbo\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/variation"];
NSDictionary *payload = @{
@"task_id": @"task_01KQVZAPBW13W63DQNQZT7FCQK",
@"index": @3,
@"speed": @"turbo",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/variation"
let payload = {|{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 3,
"speed": "turbo"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/variation');
final payload = {
'task_id': 'task_01KQVZAPBW13W63DQNQZT7FCQK',
'index': 3,
'speed': 'turbo',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/variation"
payload <- list(
task_id = "task_01KQVZAPBW13W63DQNQZT7FCQK",
index = 3,
speed = "turbo"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Creates a **subtle variation** (varySubtle, equivalent to V1–V4) from one tile of an Imagine grid. For a strong variation see [High Variation](./high-variation).
| Item | Value |
| -------- | ----------------------------------------------- |
| action | `VARIATION` |
| Billing | `midjourney@variation[-speed]` |
| Required | `task_id` + `index`, or `task_id` + `custom_id` |
| Optional | `speed`, `metadata` |
## Parameters
| Field | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `task_id` | Original task ID returned by this platform (must be SUCCESS) |
| `nsfw_check` | `boolean` — Optional; defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `index` | `1`–`4`, maps to `V1`–`V4`; one of `index` / `custom_id` |
| `custom_id` | Button ID for the corresponding action; when set, `index` auto-matching is skipped |
| `speed` | `relax` / `fast` / `turbo` |
| `metadata` | Custom metadata |
## Request example
```json theme={null}
{
"task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK",
"index": 3,
"speed": "turbo"
}
```
## Response
Submission returns a new local `task_id`. Poll `GET /v1/tasks/{task_id}`; on SUCCESS the result includes a new grid `grid_image_url` plus four `image_urls`:
```json theme={null}
{
"id": "task_xxx",
"status": "SUCCESS",
"action": "VARIATION",
"grid_image_url": "...",
"image_urls": ["...", "...", "...", "..."]
}
```
`version` / `niji` from the source task are inherited automatically (affects billing fallback). To price by speed, configure `midjourney@variation-fast` / `midjourney@variation-turbo`.
## Notes
* The parent task must be in SUCCESS state, otherwise it returns `400` (`task is not in SUCCESS state`).
* `index` must be `1`–`4`; `custom_id` and `index` are mutually exclusive.
* Defaults to `varySubtle` (subtle variation); for a strong variation use [High Variation](./high-variation); [Low Variation](./low-variation) is the same action with a different billing key and identical behavior.
# Video (image-to-video)
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/video
POST https://api.apimart.ai/v1/midjourney/generations/video
Midjourney image-to-video (i2v), fixed FAST, no t2v support, ~5 second duration
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/video \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"prompt": "the cat slowly turns its head to the camera",
"image_urls": [
"https://example.com/cat.png"
],
"motion": "high",
"batch_size": 4
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/video"
payload = {
"prompt": "the cat slowly turns its head to the camera",
"image_urls": [
"https://example.com/cat.png"
],
"motion": "high",
"batch_size": 4
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/video";
const payload = {
prompt: "the cat slowly turns its head to the camera",
image_urls: [
"https://example.com/cat.png"
],
motion: "high",
batch_size: 4
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/video"
payload := map[string]interface{}{
"prompt": "the cat slowly turns its head to the camera",
"image_urls": []string{
"https://example.com/cat.png",
},
"motion": "high",
"batch_size": 4,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/video";
String payload = """
{
"prompt": "the cat slowly turns its head to the camera",
"image_urls": [
"https://example.com/cat.png"
],
"motion": "high",
"batch_size": 4
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"the cat slowly turns its head to the camera",
"image_urls" => [
"https://example.com/cat.png",
],
"motion" => "high",
"batch_size" => 4,
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/video")
payload = {
prompt: "the cat slowly turns its head to the camera",
image_urls: [
"https://example.com/cat.png",
],
motion: "high",
batch_size: 4,
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/video")!
let payload: [String: Any] = [
"prompt": "the cat slowly turns its head to the camera",
"image_urls": [
"https://example.com/cat.png",
],
"motion": "high",
"batch_size": 4,
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/video";
var payload = @"{
""prompt"": ""the cat slowly turns its head to the camera"",
""image_urls"": [
""https://example.com/cat.png""
],
""motion"": ""high"",
""batch_size"": 4
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/video";
const char *payload = "{"
"\"prompt\":\"the cat slowly turns its head to the camera\","
"\"image_urls\":[\"https://example.com/cat.png\"],"
"\"motion\":\"high\","
"\"batch_size\":4"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/video"];
NSDictionary *payload = @{
@"prompt": @"the cat slowly turns its head to the camera",
@"image_urls": @[
@"https://example.com/cat.png",
],
@"motion": @"high",
@"batch_size": @4,
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/video"
let payload = {|{
"prompt": "the cat slowly turns its head to the camera",
"image_urls": [
"https://example.com/cat.png"
],
"motion": "high",
"batch_size": 4
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/video');
final payload = {
'prompt': 'the cat slowly turns its head to the camera',
'image_urls': [
'https://example.com/cat.png',
],
'motion': 'high',
'batch_size': 4,
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/video"
payload <- list(
prompt = "the cat slowly turns its head to the camera",
image_urls = list(
"https://example.com/cat.png"
),
motion = "high",
batch_size = 4
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Image or prompt failed content moderation; automatically refunded",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Image-to-video (i2v). **Fixed FAST mode, no speed dimension**; **text-to-video (t2v) is not supported** — a first frame is required. Duration is fixed at \~5 seconds.
| Item | Value |
| -------- | ------------------------------------------------------------------------------------- |
| action | `VIDEO` |
| Billing | `midjourney@video` / `midjourney@video-720p`, **charged = unit price × `batch_size`** |
| Required | `image_urls` (first frame) or `task_id` (reuse a SUCCESS imagine) |
## Parameters
| Field | Type | Required | Notes |
| -------------- | --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `prompt` | string | No | Default: (inherits parent); Video prompt; if empty, `task_id` is required |
| `nsfw_check` | boolean | No | Defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `image_urls` | string\[] | △ | First frame (1 image, ≤ 12 MiB); one of `image_urls` / `task_id` |
| `task_id` | string | △ | Reuse a SUCCESS imagine; one of `image_urls` / `task_id` |
| `index` | int | No | Which of the imagine 4 tiles is the first frame (`0`–`3`, with `task_id`) |
| `video_type` | string | No | Default: `vid_1.1_i2v_480`; Resolution tier (see table); `720` → `@video-720p` billing |
| `animate_mode` | string | No | Default: `manual`; `manual` / `auto`; `auto` requires `task_id` + `index` |
| `motion` | string | No | Default: `high`; `low` / `high`; motion amount, **no billing impact** |
| `batch_size` | int | No | Default: `1`; Must be `1` / `2` / `4`, other values treated as 1; **billed × N** |
| `end_url` | string | No | End frame; when set, `video_type` auto-upgrades to `start_end_*` |
## Valid video\_type values
| Value | Resolution | Mode | Billing |
| --------------------------- | ---------- | ----------------------------------------- | ----------------------- |
| `vid_1.1_i2v_480` | 480p | basic i2v (default) | `midjourney@video` |
| `vid_1.1_i2v_720` | 720p | basic i2v | `midjourney@video-720p` |
| `vid_1.1_i2v_start_end_480` | 480p | start/end frame (auto when `end_url` set) | `midjourney@video` |
| `vid_1.1_i2v_start_end_720` | 720p | start/end frame (auto when `end_url` set) | `midjourney@video-720p` |
> `extend`-style values are not accepted; only the `video_type` values listed above are supported.
## Request examples
Simple i2v (own first frame, batch 4):
```json theme={null}
{
"prompt": "the cat slowly turns its head to the camera",
"image_urls": ["https://example.com/cat.png"],
"motion": "high",
"batch_size": 4
}
```
Start/end transition (`end_url` auto-upgrades to `start_end`):
```json theme={null}
{
"prompt": "transition smoothly from sunrise to sunset",
"image_urls": ["https://example.com/sunrise.jpg"],
"end_url": "https://example.com/sunset.jpg",
"video_type": "vid_1.1_i2v_720"
}
```
## Response
Submission returns a `task_id`; poll `GET /v1/tasks/{task_id}`. On SUCCESS it includes `video_url` (the first) plus `video_urls` (`length === batch_size`; with batch=1 it still has 1 element):
```json theme={null}
{
"id": "task_xxx",
"status": "SUCCESS",
"action": "VIDEO",
"mode": "FAST",
"video_url": "https://r2.example.com/video-0.mp4",
"video_urls": [
"https://r2.example.com/video-0.mp4",
"https://r2.example.com/video-1.mp4"
]
}
```
## Notes
* **Text-to-video (t2v) is not supported**: you must pass `image_urls` or `task_id`, otherwise it returns `400`; you cannot pass both.
* **Fixed FAST mode**, no speed dimension (`@video-fast` / `@video-turbo` in the billing table are never hit).
* `batch_size` is strictly validated as `1` / `2` / `4`; **batch=4 charges 4×, use batch=1 when budget-sensitive**.
* `animate_mode=auto` requires both `task_id` + `index`.
* The first / end frame must each be ≤ 12 MiB.
# End-to-End Workflow Examples
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/workflow
End-to-end curl walkthroughs for imagine → upscale → inpaint → video, with bash / Python / TS client wrappers
End-to-end examples that chain multiple endpoints together. In all commands replace `$KEY` with your API token and `$HOST` with the actual platform domain.
```bash theme={null}
export KEY="sk-your-api-key"
export HOST="https://api.apimart.ai"
```
## Flow A: Basic text-to-image (imagine → upscale)
```bash theme={null}
# 1. imagine produces 4 images
curl -sS -X POST "$HOST/v1/midjourney/generations/imagine" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"prompt": "a futuristic city at sunset, photorealistic, cinematic lighting",
"version": "8.1", "size": "16:9", "speed": "fast", "stylize": 250
}'
# → {"code":200,"data":[{"task_id":"task_01KQVZAPBW...","status":"submitted"}]}
# 2. poll until SUCCESS (about 30–60s)
curl -sS "$HOST/v1/midjourney/task_01KQVZAPBW..." -H "Authorization: Bearer $KEY"
# → SUCCESS, includes grid_image_url + 4 image_urls + buttons(U1-U4 / V1-V4 / 🔄)
# 3. upscale the 2nd image (composed locally, SUCCESS in milliseconds)
curl -sS -X POST "$HOST/v1/midjourney/generations/upscale" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"task_id": "task_01KQVZAPBW...", "index": 2}'
# → query to get the single image image_urls[0]
```
## Flow B: Image guidance → strong variation → upscale
```bash theme={null}
# 1. image-guided imagine
curl -sS -X POST "$HOST/v1/midjourney/generations/imagine" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"prompt": "turn this product into a luxury studio photo",
"image_urls": ["https://your-cdn.example.com/product.png"],
"iw": 1.5, "size": "1:1"
}'
# 2. apply a strong variation to the result
curl -sS -X POST "$HOST/v1/midjourney/generations/high-variation" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"task_id": "task_01XXX...", "index": 1, "speed": "fast"}'
# 3. upscale one of the variation images
curl -sS -X POST "$HOST/v1/midjourney/generations/upscale" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"task_id": "task_02_variant...", "index": 3}'
```
## Flow C: Inpaint (two-step inpaint + modal)
Prerequisite: first run imagine + upscale to get a single-image task (see Flow A).
```bash theme={null}
# 1. submit inpaint → enters MODAL
curl -sS -X POST "$HOST/v1/midjourney/generations/inpaint" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"task_id": "task_02_upscaled..."}'
# → {"data":[{"task_id":"task_03_inpaint...","status":"modal"}]}
# note status=modal, the task waits for you to supply the mask; 30-minute timeout auto-cancels (CANCEL) + refund
# 2. frontend draws the mask (transparent = repaint area, white = keep), uploads it to your own OSS to get mask_url (must be publicly reachable)
# 3. submit modal to complete
curl -sS -X POST "$HOST/v1/midjourney/generations/modal" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"task_id": "task_03_inpaint...",
"prompt": "replace the selected area with a red leather sofa",
"mask_url": "https://your-oss.example.com/mask-abc.png"
}'
# → same task_id, status turns to submitted; 4. poll for 60–90s until SUCCESS, includes 4 inpaint candidates
```
## Flow D: Zoom Out
```bash theme={null}
# produces an image directly, no mask needed (neither Outpaint nor CustomZoom enters MODAL)
curl -sS -X POST "$HOST/v1/midjourney/generations/zoom" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"task_id": "task_02_upscaled...", "zoom_ratio": 1.5, "speed": "fast"}'
```
## Flow E: Image-to-video (i2v)
```bash theme={null}
# 720p HD + batch=4 (4x billing)
curl -sS -X POST "$HOST/v1/midjourney/generations/video" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"prompt": "city traffic at night, neon reflections, slow camera dolly",
"image_urls": ["https://your-cdn.example.com/city.jpg"],
"video_type": "vid_1.1_i2v_720", "batch_size": 4
}'
# actual charge = midjourney@video-720p × 4
# start/end frame transition (end_url auto-upgrades to start_end)
curl -sS -X POST "$HOST/v1/midjourney/generations/video" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"prompt": "transition smoothly from sunrise to sunset",
"image_urls": ["https://your-cdn.example.com/sunrise.jpg"],
"end_url": "https://your-cdn.example.com/sunset.jpg",
"video_type": "vid_1.1_i2v_720"
}'
```
## Shared utility: Python client wrapper
```python theme={null}
import time
import httpx
API_KEY = "sk-..."
HOST = "https://api.apimart.ai"
class MjClient:
def __init__(self):
self.client = httpx.Client(
base_url=HOST,
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=30,
)
def imagine(self, prompt, **params):
r = self.client.post("/v1/midjourney/generations/imagine",
json={"prompt": prompt, **params})
return r.json()["data"][0]["task_id"]
def upscale(self, task_id, index):
r = self.client.post("/v1/midjourney/generations/upscale",
json={"task_id": task_id, "index": index})
return r.json()["data"][0]["task_id"]
def query(self, task_id):
return self.client.get(f"/v1/midjourney/{task_id}").json()
def wait(self, task_id, timeout=180):
deadline = time.time() + timeout
while time.time() < deadline:
t = self.query(task_id)
if t["status"] in ("SUCCESS", "FAILURE"):
return t
if t["status"] == "MODAL":
raise RuntimeError(f"task {task_id} needs a /modal call")
time.sleep(3)
raise TimeoutError(task_id)
mj = MjClient()
imagine_id = mj.imagine("a cat", version="8.1", speed="fast", size="16:9")
mj.wait(imagine_id)
upscale_id = mj.upscale(imagine_id, 2)
print(mj.wait(upscale_id)["image_urls"][0])
```
## Shared utility: TypeScript wrapper
```ts theme={null}
const API_KEY = "sk-...";
const HOST = "https://api.apimart.ai";
async function mj(path: string, body: any) {
const r = await fetch(`${HOST}${path}`, {
method: "POST",
headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify(body),
});
return r.json();
}
async function query(id: string) {
const r = await fetch(`${HOST}/v1/midjourney/${id}`, {
headers: { "Authorization": `Bearer ${API_KEY}` },
});
return r.json();
}
async function waitTask(id: string, timeoutMs = 180_000) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const t = await query(id);
if (t.status === "SUCCESS" || t.status === "FAILURE") return t;
if (t.status === "MODAL") throw new Error(`needs a /modal call: ${id}`);
await new Promise((r) => setTimeout(r, 3000));
}
throw new Error(`timeout: ${id}`);
}
const r = await mj("/v1/midjourney/generations/imagine",
{ prompt: "a cat", version: "8.1", speed: "fast" });
const result = await waitTask(r.data[0].task_id);
console.log(result.image_urls);
```
## State machine
```text theme={null}
submit → NOT_START(0%) → SUBMITTED(5-30%) → IN_PROGRESS(~99%) → SUCCESS(100%)
↘ FAILURE(100%) → auto refund
inpaint / CustomZoom → MODAL(15%) ──POST /modal {mask_url, prompt}──▶ SUBMITTED → ...
└ 30min timeout → CANCEL + refund
```
# Zoom
Source: https://docs.apimart.ai/en/api-reference/images/midjourney/zoom
POST https://api.apimart.ai/v1/midjourney/generations/zoom
Zoom Out (outpaint) on a single upscaled image: the original is kept and more background is filled outward (Outpaint / CustomZoom)
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/midjourney/generations/zoom \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"zoom_ratio": 1.5,
"speed": "fast"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/midjourney/generations/zoom"
payload = {
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"zoom_ratio": 1.5,
"speed": "fast"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/midjourney/generations/zoom";
const payload = {
task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
zoom_ratio: 1.5,
speed: "fast"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/midjourney/generations/zoom"
payload := map[string]interface{}{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"zoom_ratio": 1.5,
"speed": "fast",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/midjourney/generations/zoom";
String payload = """
{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"zoom_ratio": 1.5,
"speed": "fast"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"zoom_ratio" => 1.5,
"speed" => "fast",
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/midjourney/generations/zoom")
payload = {
task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
zoom_ratio: 1.5,
speed: "fast",
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/midjourney/generations/zoom")!
let payload: [String: Any] = [
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"zoom_ratio": 1.5,
"speed": "fast",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/midjourney/generations/zoom";
var payload = @"{
""task_id"": ""task_01KQW0D3WJ2QYJP9E3H7GZ4D2R"",
""zoom_ratio"": 1.5,
""speed"": ""fast""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/midjourney/generations/zoom";
const char *payload = "{"
"\"task_id\":\"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R\","
"\"zoom_ratio\":1.5,"
"\"speed\":\"fast\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/midjourney/generations/zoom"];
NSDictionary *payload = @{
@"task_id": @"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
@"zoom_ratio": @1.5,
@"speed": @"fast",
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/midjourney/generations/zoom"
let payload = {|{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"zoom_ratio": 1.5,
"speed": "fast"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/midjourney/generations/zoom');
final payload = {
'task_id': 'task_01KQW0D3WJ2QYJP9E3H7GZ4D2R',
'zoom_ratio': 1.5,
'speed': 'fast',
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/midjourney/generations/zoom"
payload <- list(
task_id = "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
zoom_ratio = 1.5,
speed = "fast"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Task not found",
"type": "not_found_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
Zoom out (outpaint) on a single image after Upscale: the original is kept and more background is filled outward. `zoom_ratio < 2` uses Outpaint (1.5×); `≥ 2` or omitted uses CustomZoom (2×); both produce an image directly.
| Item | Value |
| -------- | ------------------------------------------ |
| action | `ZOOM` |
| Billing | `midjourney@zoom[-speed]` |
| Required | `task_id`, or `task_id` + `custom_id` |
| Optional | `zoom_ratio`, `index`, `speed`, `metadata` |
## Parameters
| Field | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `task_id` | Task ID returned by this platform (must be an Upscale single-image task) |
| `nsfw_check` | `boolean` — Optional; defaults to `false`.
Run content moderation before submitting a Midjourney task.
• `true`: use `omni-moderation-latest` to review prompts and input images
• `false`: skip moderation without adding moderation cost or latency |
| `custom_id` | Optional; button ID for the corresponding Zoom action |
| `index` | Optional; which image of the parent task (`1`–`4`, default `1`); usually unnecessary for a single image |
| `zoom_ratio` | Optional; controls which Zoom Out tier is auto-matched (see table below) |
| `speed` | `relax` / `fast` / `turbo` |
| `metadata` | Optional custom metadata |
## Auto matching
| `zoom_ratio` | Button |
| ----------------- | --------------- |
| Less than `2` | `Zoom Out 1.5x` |
| Omitted or `>= 2` | `Zoom Out 2x` |
## Request example
```json theme={null}
{
"task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R",
"zoom_ratio": 1.5,
"speed": "fast"
}
```
## Notes
* The parent task must be an **upscaled single image** and SUCCESS; passing a grid returns `This action requires an upscaled task...`, so call `upscale` first.
* Both Outpaint and CustomZoom produce an image directly, need no mask, and **do not enter MODAL** (only Inpaint uses MODAL).
* Version metadata from the source task is inherited automatically. To price by speed, configure `midjourney@zoom-fast` / `midjourney@zoom-turbo`.
## Response
On success you receive a new local `task_id`. Poll `GET /v1/tasks/{task_id}` for the result.
# Qwen Image 3.0 Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/qwen-image-3.0/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns a task ID for subsequent queries
- Supports text-to-image and image-to-image (1-3 reference images for editing)
- Supports 1K / 2K resolution, up to 6 images per request
- Standard and Pro variants (Pro is stronger for dense layout and text)
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "qwen-image-3.0",
"prompt": "A cafe poster with the title Autumn Limited, warm tones, refined layout",
"size": "16:9",
"resolution": "1K"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "qwen-image-3.0",
"prompt": "A cafe poster with the title Autumn Limited, warm tones, refined layout",
"size": "16:9",
"resolution": "1K",
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "qwen-image-3.0",
prompt: "A cafe poster with the title Autumn Limited, warm tones, refined layout",
size: "16:9",
resolution: "1K",
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JGXYZ1234567890ABCDEF"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
## Supported Models
| Model | Description | Max images | Resolution |
| -------------------- | -------------------------------------------------------------------------------- | ---------- | ---------- |
| `qwen-image-3.0` | Clear instruction following, stable text rendering; better value for general use | 6 | 1K / 2K |
| `qwen-image-3.0-pro` | Richer content; best for newspapers, storyboards, menus, exams, dense layout | 6 | 1K / 2K |
Prefer `-pro` for dense text/layout. Use `qwen-image-3.0` for general images. Prompt max \~**4.5k tokens**. Model names are not interchangeable with the 2.0 series.
## Authorizations
All endpoints require Bearer Token authentication
Get your API Key from the [API Key Management Page](https://apimart.ai/keys):
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Model name
* `qwen-image-3.0` - Standard
* `qwen-image-3.0-pro` - Pro (dense text / layout)
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation, max \~**4.5k tokens**
Reference image URL array (image-to-image / editing), **1-3 images**
* Public `http(s)://` URL or `data:image/png;base64,...` (base64 is re-uploaded first)
* Formats: JPG / JPEG / PNG / BMP / TIFF / WEBP / GIF
* Per file ≤ 10MB; width/height recommended 384-2048 px
Resolution tier (affects billing tier)
* `1K` (default; lowercase accepted)
* `2K`
You may skip the tier and pass pixels in `size` (e.g. `1600x900`). With raw pixels, area **> 2.25M pixels** bills as 2K.
Aspect ratio, or explicit pixel size
Supported ratios:
* `1:1` (default)
* `4:3` / `3:4`
* `16:9` / `9:16`
* `3:2` / `2:3`
Also accepts `16x9` style, or pixels like `1024x1024`. For custom pixels, **each edge** (width and height) must be **512–2048**, aspect ratio 1:8 \~ 8:1.
If neither `size` nor `resolution` is set, output is fixed at **1024×1024**.
Number of images, **1-6**. Values above 6 are clamped to 6.
Negative prompt: content to avoid
Intelligent prompt rewriting
Defaults to **off** for predictable results. Set to `true` to enable intelligent rewriting.
Rewrite mode (3.0 series only; requires `prompt_extend: true`)
* `direct` - works for text-to-image and image-to-image
* `agent` - **text-to-image only**, more aggressive rewrite
Invalid values are ignored.
## Size Reference Table
Combine `resolution` (tier) + `size` (ratio):
| Resolution | 1:1 | 4:3 | 3:4 | 16:9 | 9:16 | 3:2 | 2:3 |
| ---------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- |
| **1K** | 1024×1024 | 1152×864 | 864×1152 | 1280×720 | 720×1280 | 1248×832 | 832×1248 |
| **2K** | 2048×2048 | 2048×1536 | 1536×2048 | 2048×1152 | 1152×2048 | 2048×1360 | 1360×2048 |
## Use Cases
### Text-to-image (multiple)
```json theme={null}
{
"model": "qwen-image-3.0",
"prompt": "Flat illustration of a city skyline at dusk, warm orange tones",
"size": "16:9",
"resolution": "1K",
"n": 4
}
```
### Dense layout with rewrite
```json theme={null}
{
"model": "qwen-image-3.0-pro",
"prompt": "A Western restaurant menu with appetizers, mains, and desserts columns, five dishes each with prices, serif font, cream background",
"size": "3:4",
"resolution": "2K",
"prompt_extend": true,
"prompt_extend_mode": "agent"
}
```
### Image-to-image (edit)
```json theme={null}
{
"model": "qwen-image-3.0-pro",
"prompt": "Change the sign text to Open, keep everything else the same",
"image_urls": ["https://example.com/shop.jpg"],
"size": "1:1"
}
```
### Negative prompt
```json theme={null}
{
"model": "qwen-image-3.0",
"prompt": "Photorealistic mountain cabin in morning mist",
"negative_prompt": "text, watermark, people, low resolution",
"size": "3:2"
}
```
## Limits
| Item | Limit |
| ----------------- | ---------------------------------------------------- |
| Prompt | ≤ 4.5k tokens |
| Output size | Custom pixels: each edge 512–2048; aspect 1:8 \~ 8:1 |
| Image count | 1-6 (excess clamped) |
| Reference images | 1-3 |
| Reference formats | JPG / JPEG / PNG / BMP / TIFF / WEBP / GIF |
| Reference size | ≤ 10MB; width/height recommended 384-2048 px |
## Response
Status code; 200 on success
Response data array
Task status; `submitted` on create
Task ID for polling results
## Differences from 2.0
| | 2.0 series | 3.0 series |
| -------------------- | ------------- | --------------------------- |
| Prompt length | Shorter | \~4.5k tokens |
| `prompt_extend_mode` | Not supported | `direct` / `agent` |
| Resolution | 1K / 2K | 1K / 2K (Pro 2K costs more) |
| Reference images | Supported | 1-3 images |
## Notes
1. **Async**: Submit returns a `task_id`. Poll [Get Task Status](/en/api-reference/tasks/status) every **3\~5 seconds**; client timeout \~**3 minutes** (2K + multi-image is slower).
2. **Storage**: Generated images are mirrored to the platform CDN and remain available long-term.
3. **Billing**: Per delivered image × resolution tier by **actual pixel area** (> 2.25M pixels = 2K). `qwen-image-3.0` charges the same for 1K/2K; `-pro` 2K is 2× 1K. Failures are fully refunded; reference images are free.
4. **Errors**: Custom `size` edge outside 512–2048, invalid ratio, `agent` on image-to-image, unreachable/oversized references → 400; rate limit → 429.
**Query results**
Use [Get Task Status](/en/api-reference/tasks/status) for progress and `result.images`.
# Qwen Image 2.0 Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/qwen-image/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Supports text-to-image, image-to-image and other generation modes
- Supports 1K/2K resolution tiers, generate up to 6 images
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "qwen-image-2.0",
"prompt": "A cute orange cat napping in the sunshine"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "qwen-image-2.0",
"prompt": "A cute orange cat napping in the sunshine"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "qwen-image-2.0",
prompt: "A cute orange cat napping in the sunshine",
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JGXYZ1234567890ABCDEF"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance, please top up",
"type": "payment_required"
}
}
```
## Supported Models
| Model | Description | Max Images | Pricing |
| -------------------- | --------------------------------------------------------------------- | ---------- | ----------- |
| `qwen-image-2.0` | Standard version, balanced quality and performance | 6 | Fixed price |
| `qwen-image-2.0-pro` | Pro version, stronger text rendering, more refined realistic textures | 6 | Fixed price |
## Authorizations
All endpoints require Bearer Token authentication
Get API Key:
Visit [API Key Management](https://apimart.ai/keys) to get your API Key
Add to request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Model name
* `qwen-image-2.0` - Standard version, balanced quality and performance
* `qwen-image-2.0-pro` - Pro version, stronger text rendering, more refined realistic textures
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation, up to 800 characters
Image aspect ratio
Supported aspect ratios:
* `1:1` - Square (default)
* `4:3` - Landscape 4:3
* `3:4` - Portrait 3:4
* `16:9` - Landscape widescreen
* `9:16` - Portrait vertical
* `3:2` - Landscape 3:2
* `2:3` - Portrait 2:3
Resolution tier
* `1K` - Standard resolution (default)
* `2K` - High definition resolution
Number of images to generate
Range: 1-6
Negative prompt (content you don't want to appear), up to 500 characters
Reference image URL array (image-to-image mode)
**Limitations:**
* Must be publicly accessible URLs
* Base64 format not supported
## Resolution Reference Table
Output size is controlled by the combination of `size` (ratio) + `resolution` (resolution tier).
| Ratio | 1K Tier | 2K Tier |
| ------ | --------- | --------- |
| `1:1` | 1024×1024 | 2048×2048 |
| `4:3` | 1152×864 | 2048×1536 |
| `3:4` | 864×1152 | 1536×2048 |
| `16:9` | 1280×720 | 2048×1152 |
| `9:16` | 720×1280 | 1152×2048 |
| `3:2` | 1248×832 | 2048×1360 |
| `2:3` | 832×1248 | 1360×2048 |
* Only `size` → defaults to 1K tier: `{"size": "16:9"}` → 1280×720
* `size` + `resolution` → specified tier: `{"size": "16:9", "resolution": "2K"}` → 2048×1152
## Usage Examples
**Text-to-Image (minimal request)**
```json theme={null}
{
"model": "qwen-image-2.0",
"prompt": "A cute orange cat napping in the sunshine"
}
```
**Specify ratio and count**
```json theme={null}
{
"model": "qwen-image-2.0-pro",
"prompt": "Cyberpunk-style futuristic city nightscape with flickering neon lights",
"size": "16:9",
"n": 4
}
```
**High definition 2K tier**
```json theme={null}
{
"model": "qwen-image-2.0-pro",
"prompt": "Exquisite food photography, sushi platter",
"size": "4:3",
"resolution": "2K",
"n": 2
}
```
**Image-to-Image (reference image + text description)**
```json theme={null}
{
"model": "qwen-image-2.0",
"prompt": "Change the background to a seaside sunset",
"image_urls": ["https://example.com/my-photo.jpg"]
}
```
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Task unique identifier
## Notes
1. **Asynchronous Processing**: After submission, a `task_id` is returned. Poll `/v1/tasks/{task_id}` to get results
2. **Image Storage**: Generated images are mirrored to platform CDN and are valid long-term
3. **Billing Rules**: Billed per successfully generated image, no charge for failures
4. **Image URL Requirements**: Input images must be publicly accessible URLs, base64 not supported
# Seedream-4.5 Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/seedream-4.5/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Supports multiple generation modes including text-to-image, image-to-image, and image editing
- Generated image links are valid for 24 hours, please save them promptly
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "seedream-4.5",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "seedream-4.5",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "seedream-4.5",
prompt: "A cute panda playing in a bamboo forest",
size: "1:1",
resolution: "2K",
n: 1,
image_urls: [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "seedream-4.5",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": []string{
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png",
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "seedream-4.5",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"seedream-4.5",
"prompt" => "A cute panda playing in a bamboo forest",
"size" => "1:1",
"resolution" => "2K",
"n" => 1,
"image_urls" => [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "seedream-4.5",
prompt: "A cute panda playing in a bamboo forest",
size: "1:1",
resolution: "2K",
n: 1,
image_urls: [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "seedream-4.5",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""seedream-4.5"",
""prompt"": ""A cute panda playing in a bamboo forest"",
""size"": ""1:1"",
""resolution"": ""2K"",
""n"": 1,
""image_urls"": [
""https://cdn.apimart.ai/doc/1761215838466614297_9852.png""
]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/images/generations";
const char *payload = "{"
"\"model\":\"seedream-4.5\","
"\"prompt\":\"A cute panda playing in a bamboo forest\","
"\"size\":\"1:1\","
"\"resolution\":\"2K\","
"\"n\":1,"
"\"image_urls\":[\"https://cdn.apimart.ai/doc/1761215838466614297_9852.png\"]"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/images/generations"];
NSDictionary *payload = @{
@"model": @"seedream-4.5",
@"prompt": @"A cute panda playing in a bamboo forest",
@"size": @"1:1",
@"resolution": @"2K",
@"n": @1,
@"image_urls": @[
@"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/images/generations"
let payload = {|{
"model": "seedream-4.5",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'seedream-4.5',
'prompt': 'A cute panda playing in a bamboo forest',
'size': '1:1',
'resolution': '2K',
'n': 1,
'image_urls': [
'https://cdn.apimart.ai/doc/1761215838466614297_9852.png'
]
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "seedream-4.5",
prompt = "A cute panda playing in a bamboo forest",
size = "1:1",
resolution = "2K",
n = 1,
image_urls = list(
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
)
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
Supported models: `seedream-4.5`, `Seedream-4.5`, `seedream-4-5`
Example: `"seedream-4.5"`
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
Image aspect ratio
Supported aspect ratios:
* `1:1` - Square (default)
* `4:3` - Landscape 4:3
* `3:4` - Portrait 3:4
* `16:9` - Landscape widescreen
* `9:16` - Portrait vertical
* `3:2` - Landscape 3:2
* `2:3` - Portrait 2:3
* `2:1` - Extra-wide landscape
* `1:2` - Extra-tall portrait
* `21:9` - Ultra-wide
* `9:21` - Ultra-tall
* `auto` - Auto-match reference image aspect ratio (requires image\_urls)
`2x1` is equivalent to `2:1`, and `1x2` is equivalent to `1:2`. The `x` must be lowercase and spaces are not allowed.
Image resolution
Supported resolutions:
* `2K` - Standard resolution (default)
* `4K` - High definition
> **Note:** Seedream-4.5 does not support 1K resolution
**Resolution reference sizes:**
| Resolution | 1:1 Size | 16:9 Size | 2:1 Size | 1:2 Size |
| ---------- | --------- | --------- | --------- | --------- |
| 2K | 2048x2048 | 2560x1440 | 2880x1440 | 1440x2880 |
| 4K | 4096x4096 | 5404x3040 | 5760x2880 | 2880x5760 |
**2K Resolution**
| Ratio | Pixels |
| ----- | --------- |
| 1:1 | 2048x2048 |
| 4:3 | 2304x1728 |
| 3:4 | 1728x2304 |
| 16:9 | 2560x1440 |
| 9:16 | 1440x2560 |
| 3:2 | 2496x1664 |
| 2:3 | 1664x2496 |
| 2:1 | 2880x1440 |
| 1:2 | 1440x2880 |
| 21:9 | 3024x1296 |
| 9:21 | 1296x3024 |
**4K Resolution**
| Ratio | Pixels |
| ----- | --------- |
| 1:1 | 4096x4096 |
| 4:3 | 4694x3520 |
| 3:4 | 3520x4694 |
| 16:9 | 5404x3040 |
| 9:16 | 3040x5404 |
| 3:2 | 4992x3328 |
| 2:3 | 3328x4992 |
| 2:1 | 5760x2880 |
| 1:2 | 2880x5760 |
| 21:9 | 6198x2656 |
| 9:21 | 2656x6198 |
Number of images to generate
Range: 1-15 (minimum 1, maximum 15)
Default: 1
**Note:**
* **Must enter a plain number (e.g., `1`), do not use quotes or it will cause an error**
Charges will be pre-deducted based on the number
The number of reference images in `image_urls` + the final number of images specified by `n` must be ≤ 15.
Reference image URL list for image-to-image or image editing
Two formats are supported:
**1. Complete image URL**
* Publicly accessible image URL (`http://` or `https://`)
* Example: `https://example.com/image.jpg`
**2. Base64 encoded format**
* **Must use the complete Data URI format**
* Format: `data:image/{format};base64,{base64 data}`
* Supported image formats: jpeg, png
* Example: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg...`
* Note: the `data:image/jpeg;base64,` prefix is required
**Limits:**
* Image formats: jpeg, png
* Aspect ratio (width/height) range: \[1/3, 3]
* Width and height (px) > 14
* Size: not exceeding 10MB
* Total pixels: not exceeding 6000×6000 px
The number of reference images in `image_urls` + the final number of images specified by `n` must be ≤ 15.
Prompt optimization mode
* `standard`: Standard mode, generates higher quality content with longer processing time
* `fast`: Fast mode, generates content in shorter time with regular quality
Default: `standard`
Sequential image generation mode (specific feature)
Controls whether to generate multiple images:
* `disabled`: Disable sequential mode, generates only 1 image even with multiple reference images (default)
* `auto`: Enable sequential mode, can generate multiple images
**Usage Notes:**
* ✅ Must provide `image_urls` - at least 1 reference image required
* ✅ Set `n: 3` or use `sequential_image_generation: "auto"` + `max_images: 3`
* ✅ This will generate 3 different images based on reference images
* ⚠️ When `n > 1`, it will automatically be set to `auto`
**Limitations:**
* Pure text-to-image (without `image_urls`) cannot generate multiple images - this is a Doubao API limitation
Sequential image generation options
Available when `sequential_image_generation` is set to `auto`
**Properties:**
* `max_images` (integer): Specify the number of images to generate, Range: 1-15
**Example:**
```json theme={null}
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 3
}
```
Whether to add a watermark to the generated image
* `true`: Add watermark
* `false`: No watermark (default)
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
# Seedream-4.0 Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/seedream-4/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Supports multiple generation modes including text-to-image, image-to-image, and image editing
- Generated image links are valid for 24 hours, please save them promptly
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "seedream-4.0",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "seedream-4.0",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "seedream-4.0",
prompt: "A cute panda playing in a bamboo forest",
size: "1:1",
resolution: "2K",
n: 1,
image_urls: [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "seedream-4.0",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": []string{
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png",
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "seedream-4.0",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"seedream-4.0",
"prompt" => "A cute panda playing in a bamboo forest",
"size" => "1:1",
"resolution" => "2K",
"n" => 1,
"image_urls" => [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "seedream-4.0",
prompt: "A cute panda playing in a bamboo forest",
size: "1:1",
resolution: "2K",
n: 1,
image_urls: [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "seedream-4.0",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""seedream-4.0"",
""prompt"": ""A cute panda playing in a bamboo forest"",
""size"": ""1:1"",
""resolution"": ""2K"",
""n"": 1,
""image_urls"": [
""https://cdn.apimart.ai/doc/1761215838466614297_9852.png""
]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/images/generations";
const char *payload = "{"
"\"model\":\"seedream-4.0\","
"\"prompt\":\"A cute panda playing in a bamboo forest\","
"\"size\":\"1:1\","
"\"resolution\":\"2K\","
"\"n\":1,"
"\"image_urls\":[\"https://cdn.apimart.ai/doc/1761215838466614297_9852.png\"]"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/images/generations"];
NSDictionary *payload = @{
@"model": @"seedream-4.0",
@"prompt": @"A cute panda playing in a bamboo forest",
@"size": @"1:1",
@"resolution": @"2K",
@"n": @1,
@"image_urls": @[
@"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/images/generations"
let payload = {|{
"model": "seedream-4.0",
"prompt": "A cute panda playing in a bamboo forest",
"size": "1:1",
"resolution": "2K",
"n": 1,
"image_urls": [
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'seedream-4.0',
'prompt': 'A cute panda playing in a bamboo forest',
'size': '1:1',
'resolution': '2K',
'n': 1,
'image_urls': [
'https://cdn.apimart.ai/doc/1761215838466614297_9852.png'
]
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "seedream-4.0",
prompt = "A cute panda playing in a bamboo forest",
size = "1:1",
resolution = "2K",
n = 1,
image_urls = list(
"https://cdn.apimart.ai/doc/1761215838466614297_9852.png"
)
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
Supported models: `seedream-4.0`, `seedream-4-0`, `Seedream-4.0`
Example: `"seedream-4.0"`
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
Maximum 1000 characters
Image aspect ratio
Supported aspect ratios:
* `1:1` - Square (default)
* `4:3` - Landscape 4:3
* `3:4` - Portrait 3:4
* `16:9` - Landscape widescreen
* `9:16` - Portrait vertical
* `3:2` - Landscape 3:2
* `2:3` - Portrait 2:3
* `2:1` - Extra-wide landscape
* `1:2` - Extra-tall portrait
* `21:9` - Ultra-wide
* `9:21` - Ultra-tall
* `auto` - Auto-match reference image aspect ratio (requires image\_urls)
`2x1` is equivalent to `2:1`, and `1x2` is equivalent to `1:2`. The `x` must be lowercase and spaces are not allowed.
Image resolution
Supported resolutions:
* `1K` - Basic resolution
* `2K` - Standard resolution (default)
* `4K` - High definition
**Resolution reference sizes:**
| Resolution | 1:1 Size | 16:9 Size | 2:1 Size | 1:2 Size |
| ---------- | --------- | --------- | --------- | --------- |
| 1K | 1024x1024 | 1280x720 | 1440x720 | 720x1440 |
| 2K | 2048x2048 | 2560x1440 | 2880x1440 | 1440x2880 |
| 4K | 4096x4096 | 5404x3040 | 5760x2880 | 2880x5760 |
**1K Resolution**
| Ratio | Pixels |
| ----- | --------- |
| 1:1 | 1024x1024 |
| 4:3 | 1152x864 |
| 3:4 | 864x1152 |
| 16:9 | 1280x720 |
| 9:16 | 720x1280 |
| 3:2 | 1248x832 |
| 2:3 | 832x1248 |
| 2:1 | 1440x720 |
| 1:2 | 720x1440 |
| 21:9 | 1512x648 |
| 9:21 | 648x1512 |
**2K Resolution**
| Ratio | Pixels |
| ----- | --------- |
| 1:1 | 2048x2048 |
| 4:3 | 2304x1728 |
| 3:4 | 1728x2304 |
| 16:9 | 2560x1440 |
| 9:16 | 1440x2560 |
| 3:2 | 2496x1664 |
| 2:3 | 1664x2496 |
| 2:1 | 2880x1440 |
| 1:2 | 1440x2880 |
| 21:9 | 3024x1296 |
| 9:21 | 1296x3024 |
**4K Resolution**
| Ratio | Pixels |
| ----- | --------- |
| 1:1 | 4096x4096 |
| 4:3 | 4694x3520 |
| 3:4 | 3520x4694 |
| 16:9 | 5404x3040 |
| 9:16 | 3040x5404 |
| 3:2 | 4992x3328 |
| 2:3 | 3328x4992 |
| 2:1 | 5760x2880 |
| 1:2 | 2880x5760 |
| 21:9 | 6198x2656 |
| 9:21 | 2656x6198 |
Number of images to generate
Range: 1-15 (minimum 1, maximum 15)
Default: 1
**Note:**
* **Must enter a plain number (e.g., `1`), do not use quotes or it will cause an error**
Charges will be pre-deducted based on the number
The number of reference images in `image_urls` + the final number of generated images specified by `n` must be ≤ 15.
Reference image URL list for image-to-image or image editing
Two formats supported:
**1. Full image URL**
* Publicly accessible image URL (http\:// or https\://)
* Example: `https://example.com/image.jpg`
**2. Base64 encoded format**
* **Must use the complete Data URI format**
* Format: `data:image/{format};base64,{base64-data}`
* Supported image formats: jpeg, png
* Example: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg...`
* ⚠️ Note: Must include the `data:image/jpeg;base64,` prefix
**Limits:**
* Image formats: jpeg, png
* Aspect ratio (width/height) range: \[1/3, 3]
* Width and height (px) > 14
* Size: not exceeding 10MB
* Total pixels: not exceeding 6000×6000 px
The number of reference images in `image_urls` + the final number of generated images specified by `n` must be ≤ 15.
Prompt optimization mode
* `standard`: Standard mode, generates higher quality content with longer processing time
* `fast`: Fast mode, generates content in shorter time with regular quality
Default: `standard`
Sequential image generation mode (specific feature)
Controls whether to generate multiple images:
* `disabled`: Disable sequential mode, generates only 1 image even with multiple reference images (default)
* `auto`: Enable sequential mode, can generate multiple images
**Usage Notes:**
* ✅ Must provide `image_urls` - at least 1 reference image required
* ✅ Set `n: 3` or use `sequential_image_generation: "auto"` + `max_images: 3`
* ✅ This will generate 3 different images based on reference images
* ⚠️ When `n > 1`, it will automatically be set to `auto`
**Limitations:**
* Pure text-to-image (without `image_urls`) cannot generate multiple images - this is a Doubao API limitation
Sequential image generation options
Available when `sequential_image_generation` is set to `auto`
**Properties:**
* `max_images` (integer): Specify the number of images to generate, Range: 1-15
**Example:**
```json theme={null}
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 3
}
```
Whether to add a watermark to the generated image
* `true`: Add watermark
* `false`: No watermark (default)
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
# Seedream-5.0-Pro Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/seedream-5-0-pro/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns a task ID for subsequent queries
- Supports text-to-image, single-image-to-image, and multi-reference image-to-image (up to 10 reference images)
- Supports 1K / 1.5K / 2K resolution tiers, or exact pixels via `size`
- Single-image model: one image per request; PNG / JPEG output
- Generated image links are valid for 72 hours; please save them promptly
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "seedream-5-0-pro",
"prompt": "A cyberpunk city night scene, neon lights reflecting on wet streets",
"size": "16:9",
"resolution": "2K"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "seedream-5-0-pro",
"prompt": "A cyberpunk city night scene, neon lights reflecting on wet streets",
"size": "16:9",
"resolution": "2K"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "seedream-5-0-pro",
prompt: "A cyberpunk city night scene, neon lights reflecting on wet streets",
size: "16:9",
resolution: "2K"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "seedream-5-0-pro",
"prompt": "A cyberpunk city night scene, neon lights reflecting on wet streets",
"size": "16:9",
"resolution": "2K",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "seedream-5-0-pro",
"prompt": "A cyberpunk city night scene, neon lights reflecting on wet streets",
"size": "16:9",
"resolution": "2K"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"seedream-5-0-pro",
"prompt" => "A cyberpunk city night scene, neon lights reflecting on wet streets",
"size" => "16:9",
"resolution" => "2K"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "seedream-5-0-pro",
prompt: "A cyberpunk city night scene, neon lights reflecting on wet streets",
size: "16:9",
resolution: "2K"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "seedream-5-0-pro",
"prompt": "A cyberpunk city night scene, neon lights reflecting on wet streets",
"size": "16:9",
"resolution": "2K"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""seedream-5-0-pro"",
""prompt"": ""A cyberpunk city night scene, neon lights reflecting on wet streets"",
""size"": ""16:9"",
""resolution"": ""2K""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/images/generations";
const char *payload = "{"
"\"model\":\"seedream-5-0-pro\","
"\"prompt\":\"A cyberpunk city night scene, neon lights reflecting on wet streets\","
"\"size\":\"16:9\","
"\"resolution\":\"2K\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/images/generations"];
NSDictionary *payload = @{
@"model": @"seedream-5-0-pro",
@"prompt": @"A cyberpunk city night scene, neon lights reflecting on wet streets",
@"size": @"16:9",
@"resolution": @"2K"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/images/generations"
let payload = {|{
"model": "seedream-5-0-pro",
"prompt": "A cyberpunk city night scene, neon lights reflecting on wet streets",
"size": "16:9",
"resolution": "2K"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'seedream-5-0-pro',
'prompt': 'A cyberpunk city night scene, neon lights reflecting on wet streets',
'size': '16:9',
'resolution': '2K'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "seedream-5-0-pro",
prompt = "A cyberpunk city night scene, neon lights reflecting on wet streets",
size = "16:9",
resolution = "2K"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
**Single-image model**: `seedream-5-0-pro` generates only 1 image per request (except layer decomposition). The following are **rejected** (HTTP 400, no task, no charge):
* `n > 1`
* `sequential_image_generation` (group generation is not supported)
* `stream` (streaming is not supported)
* `tools` (web search is not supported)
* more than 10 items in `image_urls`
Use `` / `` coordinates in the prompt, or upload an image with hand-drawn annotations, to target edits precisely.
* Point coordinates: `x y` (specify a single point; the model determines the affected area)
* Bounding-box coordinates: `x1 y1 x2 y2` (specify the top-left and bottom-right coordinates to precisely control the size of the edit area)
Split one image into a base image and up to 16 transparent PNG layers, with position and stacking information.
## Body
Image generation model name
* `seedream-5-0-pro` (recommended)
* Also accepted: `seedream-5.0-pro`
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
Optional when `layer_decomposition: true`; if omitted, the model automatically identifies and separates the main elements in the image.
In addition to Chinese and English, native text generation supports Russian, Arabic, Filipino, Thai, Turkish, Korean, Malay, Spanish, Portuguese, Indonesian, French, German, Vietnamese, and Japanese.
> **Tip:** Keep it within 600 English words; overly long descriptions may lose detail.
Resolution tier (lowercase accepted). This is an API Mart extension equivalent to placing the tier directly in `size`.
* `1K` (default)
* `1.5K` (same price as 1K, better quality — prefer 1.5K unless you have a reason not to)
* `2K`
Unsupported tiers such as 3K / 4K return 400.
If both a tier-style `size` and `resolution` are provided, `size` takes precedence.
When `size` is an **exact pixel value** (e.g. `2048x1024`), this field is **ignored** and dimensions come only from `size`.
A tier keyword, aspect ratio, `auto`, or **exact pixel dimensions**.
### Style ①: resolution tier (recommended)
The tier can be placed directly in `size`, or supplied through the API Mart extension field `resolution`:
```json theme={null}
{ "size": "2K" }
```
```json theme={null}
{ "resolution": "2K" }
```
These forms are equivalent. When only a tier is specified, describe the intended layout in the prompt (for example, "portrait poster" or "landscape cover") and let the model choose the aspect ratio.
### Style ②: tier + aspect ratio
Used with `resolution`. Supported ratios:
* `1:1`, `4:3`, `3:4`, `16:9`, `9:16`, `3:2`, `2:3`, `2:1`, `1:2`, `21:9`
* Also accepts `16x9`-style `x` separators
* `2x1` is equivalent to `2:1`, and `1x2` is equivalent to `1:2`. The `x` must be lowercase and spaces are not allowed.
* `auto` (default): only the resolution tier is applied; final aspect ratio is chosen from the prompt / references
Ratios outside the list (e.g. `9:21`) return 400 — **no silent fallback to 1:1**.
**Tier × ratio → output pixels:**
| Resolution | 1:1 | 4:3 | 3:4 | 16:9 | 9:16 | 3:2 | 2:3 | 2:1 | 1:2 | 21:9 |
| ---------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- |
| **1K** | 1024×1024 | 1152×864 | 864×1152 | 1312×736 | 736×1312 | 1248×832 | 832×1248 | 1440×720 | 720×1440 | 1568×672 |
| **1.5K** | 1536×1536 | 1792×1344 | 1344×1792 | 2048×1152 | 1152×2048 | 1872×1248 | 1248×1872 | 2176×1088 | 1088×2176 | 2352×1008 |
| **2K** | 2048×2048 | 2304×1728 | 1728×2304 | 2560×1440 | 1440×2560 | 2496×1664 | 1664×2496 | 2880×1440 | 1440×2880 | 3024×1296 |
```json theme={null}
{ "resolution": "2K", "size": "2:1" }
```
### Style ③: exact pixels
When `size` is `widthxheight`, pixels are used as-is and `resolution` does not apply. Accepts `2048X1024` / `2048×1024`.
| Constraint | Range |
| ----------------------------- | ------------------------------------------------------------ |
| Total pixels (width × height) | `[921600, 4624220]` (about `1280×720` \~ `2048×2048×1.1025`) |
| Aspect ratio (width / height) | `[1/16, 16]` |
Limits apply to the **product** of width and height, not each edge alone. Example: `512×512` is too small (400); `2048×1024` is valid.
Output background mode:
* `opaque`: solid background (default)
* `transparent`: transparent background
`transparent` is available only for image-to-image requests with exactly one input image that already has an alpha channel; `output_format: "png"` is also required.
Whether to decompose the image into layers. When enabled, the model returns one base image and up to 16 PNG layers with alpha channels.
Exactly one PNG or JPEG image is required. It must contain `[262144, 36000000]` total pixels and be no larger than 30 MB. `size` accepts only `1K`, `1.5K`, `2K`, or `auto` and defaults to `auto`. `output_format` controls only the base image format; decomposed layers are always PNG.
Prompt optimization mode:
* `standard`: standard mode with better quality (default)
The flattened form `"optimize_prompt_options.mode": "standard"` is also accepted.
Number of images to generate. Only `1` is supported; use `seedream-5-0-lite` for grouped image generation.
Reference image URL list for single / multi-reference image-to-image, **up to 10**
Two formats:
**1. Public URL**
* `http://` or `https://`
* Example: `https://example.com/image.jpg`
**2. Base64 (Data URI)**
* Format: `data:image/;base64,` — `` must be **lowercase**
* Example: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg...`
**Per-image limits:**
* Formats: jpeg / png / webp / bmp / tiff / gif / heic / heif
* Aspect ratio (w/h): `[1/16, 16]`
* Each edge > 14 px
* Size ≤ 30 MB
* Total pixels ≤ `6000×6000` (36,000,000)
> **Billing:** First reference image free; each additional image has a fixed surcharge.
Output image format
* `jpeg` (default)
* `png`
> **Compatibility:** `response_format` is equivalent to `output_format`; other values are treated as `jpeg`.
Whether to add an "AI generated" watermark at the bottom-right
* `true`: add watermark
* `false`: no watermark (default)
## Request Examples
### Text-to-image (tier + ratio)
```json theme={null}
{
"model": "seedream-5-0-pro",
"prompt": "Cyberpunk city night scene, neon reflections on wet streets",
"resolution": "2K",
"size": "2:1",
"output_format": "png"
}
```
### Text-to-image (exact pixels)
```json theme={null}
{
"model": "seedream-5-0-pro",
"prompt": "Minimal e-commerce hero image, white background, product centered",
"size": "1600x1600"
}
```
### Multi-reference
```json theme={null}
{
"model": "seedream-5-0-pro",
"prompt": "Replace the outfit in image 1 with the outfit in image 2",
"image_urls": [
"https://example.com/person.jpg",
"https://example.com/dress.jpg"
],
"resolution": "2K",
"size": "auto"
}
```
### Recommended: 1.5K same price, better quality
```json theme={null}
{
"model": "seedream-5-0-pro",
"prompt": "A cute orange cat on a windowsill in afternoon sun, cinematic",
"resolution": "1.5K",
"size": "16:9"
}
```
### Layer decomposition
```json theme={null}
{
"model": "seedream-5-0-pro",
"image_urls": ["https://example.com/poster.png"],
"layer_decomposition": true,
"size": "2K"
}
```
You can also use `` coordinates normalized to `0–1000` to identify elements to extract precisely:
```json theme={null}
{
"model": "seedream-5-0-pro",
"prompt": "Separate the image into precise layers. The text is at 180 64 812 198; the parrot is at 347 305 642 997.",
"image_urls": ["https://example.com/poster.png"],
"layer_decomposition": true
}
```
### Interactive editing
Describe hand-drawn annotations in the image using natural language:
```json theme={null}
{
"model": "seedream-5-0-pro",
"prompt": "Edit the image according to the sketch. Add a stack of magazines in the marked area at the lower left and a cup of coffee in the marked area on the right. Remove all sketch lines and preserve the composition.",
"image_urls": ["https://example.com/sketch.png"],
"size": "2K",
"output_format": "png"
}
```
Or target locations precisely with `` / ``:
```json theme={null}
{
"model": "seedream-5-0-pro",
"prompt": "Place the subject from image 1 at 179 283 796 986 into image 2 at 118 331 933 871.",
"image_urls": [
"https://example.com/a.png",
"https://example.com/b.png"
]
}
```
### Alpha-channel editing
```json theme={null}
{
"model": "seedream-5-0-pro",
"prompt": "Change the parrot into a peacock while preserving the transparent background",
"image_urls": ["https://cdn.example.com/images/layer.png"],
"background": "transparent",
"output_format": "png",
"size": "2K"
}
```
## Complete example: submit a task and retrieve the image
The following script shows the full flow: submit an asynchronous task, poll its status, handle failure states, and read the final image URL. Replace `YOUR_API_KEY` before running it.
```python Python theme={null}
import time
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.apimart.ai"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
# 1. Submit the generation task
create_response = requests.post(
f"{BASE_URL}/v1/images/generations",
headers=headers,
json={
"model": "seedream-5-0-pro",
"prompt": "A Jiangnan water town in ink-wash style, with light morning mist",
"resolution": "1.5K",
"size": "16:9",
"output_format": "png",
},
timeout=30,
)
create_response.raise_for_status()
task_id = create_response.json()["data"][0]["task_id"]
print(f"Task submitted: {task_id}")
# 2. Poll task status
while True:
task_response = requests.get(
f"{BASE_URL}/v1/tasks/{task_id}",
headers=headers,
timeout=30,
)
task_response.raise_for_status()
task = task_response.json()
status = task["status"]
print(f"Status: {status}; progress: {task.get('progress', 0)}%")
if status == "success":
image = task["result"]["images"][0]
print("Image URL:", image["url"][0])
print("Image size:", image["sizes"][0])
print("Image format:", image["output_formats"][0])
break
if status in {"failed", "cancelled"}:
raise RuntimeError(task.get("error", f"Task {status}"))
time.sleep(5)
```
On success, the task query endpoint returns:
```json theme={null}
{
"id": "task_01JFXYZ123456789ABCDEF",
"status": "success",
"progress": 100,
"cost": 0.045,
"result": {
"images": [
{
"url": ["https://cdn.example.com/images/image_task_xxx_0.png"],
"sizes": ["2048x1152"],
"output_formats": ["png"],
"expires_at": 1784696685
}
]
}
}
```
Returned images are mirrored to storage managed by the platform. You should still download and persist them in your own system promptly; do not treat the result URL as permanent storage.
## Complete cURL scenarios
### Multi-image composition (up to 10 references)
```bash theme={null}
curl -X POST "https://api.apimart.ai/v1/images/generations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedream-5-0-pro",
"prompt": "Place the person from image 1 into the scene from image 2 and unify the lighting at dusk",
"image_urls": [
"https://example.com/person.jpg",
"https://example.com/scene.jpg"
],
"resolution": "1.5K",
"size": "16:9",
"output_format": "png"
}'
```
### Exact pixels, prompt optimization, and watermark
```bash theme={null}
curl -X POST "https://api.apimart.ai/v1/images/generations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedream-5-0-pro",
"prompt": "A cyberpunk city skyline with neon lights reflected on wet streets",
"size": "2048x1024",
"optimize_prompt_options": { "mode": "standard" },
"watermark": true
}'
```
### Decompose and edit a transparent layer independently
First, decompose the source image:
```bash theme={null}
curl -X POST "https://api.apimart.ai/v1/images/generations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedream-5-0-pro",
"image_urls": ["https://example.com/poster.png"],
"layer_decomposition": true,
"size": "2K"
}'
```
Then retrieve the URL of a transparent layer and edit it independently:
```bash theme={null}
curl -X POST "https://api.apimart.ai/v1/images/generations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedream-5-0-pro",
"prompt": "Change the parrot in the image into a peacock",
"image_urls": ["https://cdn.example.com/images/image_task_xxx_4.png"],
"background": "transparent",
"output_format": "png",
"size": "2K"
}'
```
## Layer-decomposition response and reconstruction
The `url`, `sizes`, `output_formats`, and `layers` arrays correspond by index; index `0` is always the base image:
```json theme={null}
{
"result": {
"images": [{
"url": [
"https://cdn.example.com/images/image_task_xxx_0.jpeg",
"https://cdn.example.com/images/image_task_xxx_1.png",
"https://cdn.example.com/images/image_task_xxx_2.png"
],
"sizes": ["2048x2048", "1273x265", "492x98"],
"output_formats": ["jpeg", "png", "png"],
"layer_decomposition": true,
"layers": [
{ "z_index": 0, "size": "2048x2048", "output_format": "jpeg" },
{
"z_index": 1,
"size": "1273x265",
"output_format": "png",
"name": "Title text",
"description": "Large yellow title text in a serif typeface",
"bounding_box": {
"absolute": [383, 120, 1655, 384],
"normalized": [187, 59, 808, 188]
}
},
{
"z_index": 2,
"size": "492x98",
"output_format": "png",
"name": "Upper-left tagline",
"description": "Two-line English tagline in white",
"bounding_box": {
"absolute": [140, 451, 631, 548],
"normalized": [68, 220, 308, 268]
}
}
]
}]
}
}
```
Composite layers in ascending `z_index` order. To reconstruct them on the output base image with absolute coordinates:
```text theme={null}
x = left
y = top
w = right - left
h = bottom - top
```
To reconstruct them on any `W × H` canvas, use normalized coordinates:
```text theme={null}
x = left / 1000 × W
y = top / 1000 × H
w = (right - left) / 1000 × W
h = (bottom - top) / 1000 × H
```
Layer decomposition is billed per image. Up to 17 images are preauthorized when the task is submitted. After completion, each output is assigned a tier based on its actual pixel count and settled individually; any excess preauthorization is refunded automatically. Your balance must cover the 17-image preauthorization, and `size: "auto"` is preauthorized at the 2K tier.
## Billing Notes
```
Total = output unit price + reference surcharge × max(0, ref_count − 1)
```
Output is priced by **actual total pixels** (\~2.61M = 2,601,124):
| Condition | Unit price |
| ----------------------------------------------------------------------------------------------------- | ------------------- |
| ≤ 2.61 million pixels (1.5K or lower: `resolution` `1K` / `1.5K` / omit, or exact pixels ≤ 2,601,124) | **\$0.045** / image |
| > 2.61 million pixels (higher than 1.5K: `resolution: "2K"`, or exact pixels > 2,601,124) | **\$0.09** / image |
* **1.5K costs the same as 1K** (\$0.045).
* With exact-pixel `size`, billing uses **actual output area**; `resolution` is ignored (e.g. `size: "2048x2048"` → \$0.09).
* First reference image is free; each additional reference has a surcharge.
* Failed tasks are fully refunded.
### Layer-decomposition preauthorization and settlement
Because the final number and dimensions of layers are unknown when a task is submitted, preauthorization uses conservative rules based on the request:
* Exact pixels: tiered by the requested pixel area.
* `1K` / `1.5K`: preauthorized at the 1K tier.
* `2K`: preauthorized at the 2K tier.
* `auto`: can output up to 2K, so it is preauthorized at the 2K tier.
After completion, the base image and every actual layer are **tiered and summed individually** using their real pixel areas. Excess preauthorization is refunded automatically. Layers are usually much smaller than the base image, so even a task preauthorized at the 2K tier may ultimately settle entirely at the 1K tier.
Example: a `1080×1080` input is decomposed into 10 images. The task is preauthorized as `17 images × 2K tier`. If all 10 final images contain no more than 2.61 million pixels, settlement uses `10 images × 1K tier` and the remaining credit is refunded automatically.
## Common Errors
| Case | Notes |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| Unsupported `resolution` tier | e.g. 3K / 4K → 400 |
| Unsupported `size` value | Neither `1K` / `1.5K` / `2K` / `auto`, a supported aspect ratio, nor valid pixel dimensions → 400 |
| Exact-pixel total out of range | Must be in `[921600, 4624220]` |
| Exact-pixel aspect out of range | Must be in `[1/16, 16]` |
| `n > 1` / grouped-image parameters | Rejected by the single-image model |
| More than 10 reference images | Rejected |
| Layer decomposition without an image or with multiple images | Exactly one image is required |
| Layer decomposition with a ratio or exact pixels | `size` supports only `1K` / `1.5K` / `2K` / `auto` |
| Transparent background for text-to-image or multiple inputs | Exactly one input image with an alpha channel is required |
| Transparent background with JPEG | Set `output_format: "png"` |
| `stream` / `tools` | Not supported by this model; returns 400 |
| Invalid prompt optimization mode | Only `standard` is supported |
⏱️ **Slower generation**: \~90s for 1K, \~160s for 2K (quality first). Poll [Get Task Status](/en/api-reference/tasks/status) every 5–10 seconds; set the client timeout to **5 minutes**. Save generated results promptly.
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
# Seedream-5.0-Lite Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/seedream-5-lite/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Supports multiple generation modes including text-to-image, image-to-image, and sequential image generation
- Supports 2K / 3K resolution with PNG / JPEG output formats
- Generated image links are valid for 72 hours, please save them promptly
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "seedream-5-0-lite",
"prompt": "A golden retriever playing in a garden, sunny day, high-definition photography style",
"size": "16:9",
"resolution": "2K",
"n": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "seedream-5-0-lite",
"prompt": "A golden retriever playing in a garden, sunny day, high-definition photography style",
"size": "16:9",
"resolution": "2K",
"n": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "seedream-5-0-lite",
prompt: "A golden retriever playing in a garden, sunny day, high-definition photography style",
size: "16:9",
resolution: "2K",
n: 1
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "seedream-5-0-lite",
"prompt": "A golden retriever playing in a garden, sunny day, high-definition photography style",
"size": "16:9",
"resolution": "2K",
"n": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/images/generations";
String payload = """
{
"model": "seedream-5-0-lite",
"prompt": "A golden retriever playing in a garden, sunny day, high-definition photography style",
"size": "16:9",
"resolution": "2K",
"n": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"seedream-5-0-lite",
"prompt" => "A golden retriever playing in a garden, sunny day, high-definition photography style",
"size" => "16:9",
"resolution" => "2K",
"n" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "seedream-5-0-lite",
prompt: "A golden retriever playing in a garden, sunny day, high-definition photography style",
size: "16:9",
resolution: "2K",
n: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "seedream-5-0-lite",
"prompt": "A golden retriever playing in a garden, sunny day, high-definition photography style",
"size": "16:9",
"resolution": "2K",
"n": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/images/generations";
var payload = @"{
""model"": ""seedream-5-0-lite"",
""prompt"": ""A golden retriever playing in a garden, sunny day, high-definition photography style"",
""size"": ""16:9"",
""resolution"": ""2K"",
""n"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/images/generations";
const char *payload = "{"
"\"model\":\"seedream-5-0-lite\","
"\"prompt\":\"A golden retriever playing in a garden\","
"\"size\":\"16:9\","
"\"resolution\":\"2K\","
"\"n\":1"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/images/generations"];
NSDictionary *payload = @{
@"model": @"seedream-5-0-lite",
@"prompt": @"A golden retriever playing in a garden",
@"size": @"16:9",
@"resolution": @"2K",
@"n": @1
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/images/generations"
let payload = {|{
"model": "seedream-5-0-lite",
"prompt": "A golden retriever playing in a garden",
"size": "16:9",
"resolution": "2K",
"n": 1
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/images/generations');
final payload = {
'model': 'seedream-5-0-lite',
'prompt': 'A golden retriever playing in a garden, sunny day, high-definition photography style',
'size': '16:9',
'resolution': '2K',
'n': 1
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/images/generations"
payload <- list(
model = "seedream-5-0-lite",
prompt = "A golden retriever playing in a garden, sunny day, high-definition photography style",
size = "16:9",
resolution = "2K",
n = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image generation model name
Supported models: `seedream-5-0-lite`, `seedream-5.0-lite`, `Seedream-5.0-lite`
Example: `"seedream-5-0-lite"`
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation
Image aspect ratio
Supported aspect ratios:
* `1:1` - Square (default)
* `4:3` - Landscape 4:3
* `3:4` - Portrait 3:4
* `16:9` - Landscape widescreen
* `9:16` - Portrait vertical
* `3:2` - Landscape 3:2
* `2:3` - Portrait 2:3
* `2:1` - Extra-wide landscape
* `1:2` - Extra-tall portrait
* `21:9` - Ultra-wide
* `auto` - Auto-match reference image aspect ratio (requires image\_urls)
`2x1` is equivalent to `2:1`, and `1x2` is equivalent to `1:2`. The `x` must be lowercase and spaces are not allowed.
> **Note:** Seedream-5.0-Lite does not support `9:21` ratio
Image resolution
Supported resolutions:
* `2K` - Standard resolution (default)
* `3K` - High definition
* `4K` - Ultra high definition
> **Note:** Seedream-5.0-Lite supports 2K, 3K, and 4K resolutions, and does not support 1K
**Resolution reference sizes:**
| Resolution | 1:1 Size | 16:9 Size | 2:1 Size | 1:2 Size |
| ---------- | --------- | --------- | --------- | --------- |
| 2K | 2048x2048 | 2848x1600 | 2880x1440 | 1440x2880 |
| 3K | 3072x3072 | 4096x2304 | 4320x2160 | 2160x4320 |
| 4K | 4096x4096 | 5504x3040 | 5760x2880 | 2880x5760 |
**2K Resolution**
| Ratio | Pixels |
| ----- | --------- |
| 1:1 | 2048×2048 |
| 4:3 | 2304×1728 |
| 3:4 | 1728×2304 |
| 16:9 | 2848×1600 |
| 9:16 | 1600×2848 |
| 3:2 | 2496×1664 |
| 2:3 | 1664×2496 |
| 2:1 | 2880×1440 |
| 1:2 | 1440×2880 |
| 21:9 | 3136×1344 |
**3K Resolution**
| Ratio | Pixels |
| ----- | --------- |
| 1:1 | 3072×3072 |
| 4:3 | 3456×2592 |
| 3:4 | 2592×3456 |
| 16:9 | 4096×2304 |
| 9:16 | 2304×4096 |
| 3:2 | 3744×2496 |
| 2:3 | 2496×3744 |
| 2:1 | 4320×2160 |
| 1:2 | 2160×4320 |
| 21:9 | 4704×2016 |
**4K Resolution**
| Ratio | Pixels |
| ----- | --------- |
| 1:1 | 4096×4096 |
| 4:3 | 4704×3520 |
| 3:4 | 3520×4704 |
| 16:9 | 5504×3040 |
| 9:16 | 3040×5504 |
| 3:2 | 4992×3328 |
| 2:3 | 3328×4992 |
| 2:1 | 5760×2880 |
| 1:2 | 2880×5760 |
| 21:9 | 6240×2656 |
Number of images to generate
Range: 1-15
Default: 1
**Note:**
* When `n > 1`, sequential image generation mode is automatically enabled
* **Must enter a plain number (e.g., `1`), do not use quotes or it will cause an error**
Charges will be pre-deducted based on the number
The number of reference images in `image_urls` + the final number of generated images specified by `n` must be ≤ 15.
Reference image URL list for image-to-image generation
Two formats are supported:
**1. Full image URL**
* Publicly accessible image URL (http\:// or https\://)
* Example: `https://example.com/image.jpg`
**2. Base64 encoded format**
* **Must use the full Data URI format**
* Format: `data:image/{format};base64,{base64data}`
* Supported image formats: jpeg, png
* Example: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg...`
* ⚠️ Note: Must include the `data:image/jpeg;base64,` prefix
**Limitations:**
* Image formats: jpeg, png
* Aspect ratio (width/height) range: \[1/3, 3]
* Width and height (px) > 14
* Size: not exceeding 10MB per image
* Total pixels: not exceeding 6000×6000 px
The number of reference images in `image_urls` + the final number of generated images specified by `n` must be ≤ 15.
Output image format
* `jpeg`: JPEG format (default)
* `png`: PNG format, suitable for transparent backgrounds and similar use cases
> **Note:** The `output_format` parameter is exclusive to Seedream-5.0-Lite. Other image models will ignore this parameter.
Sequential image generation mode
Controls whether to generate multiple images:
* `disabled`: Disable sequential mode (default)
* `auto`: Enable sequential mode, can generate multiple images
**Usage Notes:**
* When `n > 1`, it will automatically be set to `auto`
Sequential image generation options
Available when `sequential_image_generation` is set to `auto`
**Properties:**
* `max_images` (integer): Specify the number of images to generate
**Example:**
```json theme={null}
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 4
}
```
Whether to add a watermark to the generated image
* `true`: Add watermark
* `false`: No watermark (default)
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
# wan2.7 Image Generation & Editing
Source: https://docs.apimart.ai/en/api-reference/images/wan2.7-image/generation
POST https://api.apimart.ai/v1/images/generations
- Wan2.7 image series: supports text-to-image, image editing, interactive editing, sequential generation, and multi-image reference
- Asynchronous processing mode — submit a task and poll for results using the returned task_id
- Supports 1K / 2K / 4K resolution; wan2.7-image-pro supports up to 4K for text-to-image
- Billing is based on the number of successfully generated images, regardless of resolution or aspect ratio
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.7-image-pro",
"prompt": "A flower shop with exquisite windows, beautiful wooden door, flowers on display"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "wan2.7-image-pro",
"prompt": "A flower shop with exquisite windows, beautiful wooden door, flowers on display"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "wan2.7-image-pro",
prompt: "A flower shop with exquisite windows, beautiful wooden door, flowers on display"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/images/generations"
payload := map[string]interface{}{
"model": "wan2.7-image-pro",
"prompt": "A flower shop with exquisite windows, beautiful wooden door, flowers on display",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String payload = """
{
"model": "wan2.7-image-pro",
"prompt": "A flower shop with exquisite windows, beautiful wooden door, flowers on display"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.apimart.ai/v1/images/generations"))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
System.out.println(client.send(request,
HttpResponse.BodyHandlers.ofString()).body());
}
}
```
```php PHP theme={null}
"wan2.7-image-pro",
"prompt" => "A flower shop with exquisite windows, beautiful wooden door, flowers on display"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/images/generations")
payload = {
model: "wan2.7-image-pro",
prompt: "A flower shop with exquisite windows, beautiful wooden door, flowers on display"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/images/generations")!
let payload: [String: Any] = [
"model": "wan2.7-image-pro",
"prompt": "A flower shop with exquisite windows, beautiful wooden door, flowers on display"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error { print("Error: \(error)"); return }
if let data = data, let str = String(data: data, encoding: .utf8) { print(str) }
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var payload = @"{
""model"": ""wan2.7-image-pro"",
""prompt"": ""A flower shop with exquisite windows, beautiful wooden door, flowers on display""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(
"https://api.apimart.ai/v1/images/generations", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
```
```json 200 theme={null}
{
"code": "success",
"data": [
{
"task_id": "task_01HX...",
"status": "processing"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Please check your API key.",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account.",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests. Please try again later.",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later.",
"type": "server_error"
}
}
```
## Authorizations
All requests require Bearer Token authentication.
Visit the [API Key Management page](https://apimart.ai/keys) to obtain your API Key, then add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Available Models
| Model | Description | Max Resolution (Text-to-Image) | Max Resolution (Edit / Sequential) | Price |
| ------------------ | ------------------------------------------------- | :----------------------------: | :--------------------------------: | ------------- |
| `wan2.7-image-pro` | Professional edition, better details, supports 4K | 4K | 2K | ¥0.50 / image |
| `wan2.7-image` | Standard edition, faster generation | 2K | 2K | ¥0.20 / image |
Billing is based on **successfully generated images × unit price**. Input is not billed. Resolution and aspect ratio do not affect pricing. Failed requests are not charged.
## Body
Image generation model name.
* `wan2.7-image-pro` — Professional edition, up to 4K for text-to-image
* `wan2.7-image` — Standard edition, faster, up to 2K
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation, up to 5000 characters.
* **Text-to-image** (no `image_urls`): required
* **Image editing** (with `image_urls`): optional but recommended
Example: `"A flower shop with exquisite windows, beautiful wooden door, flowers on display"`
Input image URL array for editing and multi-image reference scenarios.
Providing this field switches the request to **image editing mode**.
**Supported formats:** HTTP/HTTPS URLs; `data:image/...;base64,...` Base64
**Constraints:** Up to 9 images; JPEG / PNG / WEBP / BMP; 240–8000 px, aspect ratio 1:8 \~ 8:1; ≤ 20MB per image
Output aspect ratio automatically matches the **last** input image. Editing mode supports up to 2K only — 4K is not available.
Number of images to generate.
* **Standard mode**: 1–4 (default 1)
* **Sequential mode** (`enable_sequential: true`): 1–12 (default 1)
Billed per successfully generated image. Pre-charged based on `n`.
Output resolution or aspect ratio. Supports three formats:
**① Resolution keyword (recommended):** `1K` / `2K` (default) / `4K` (`wan2.7-image-pro` text-to-image only)
**② Aspect ratio:** `1:1` / `16:9` / `9:16` / `4:3` / `3:4` / `3:2` / `2:3` (defaults to 2K tier)
**③ Pixel dimensions:** `1024x1024` or `1024*1024`
Resolution tier keyword: `1K` / `2K` / `4K`. Can be combined with `size` (aspect ratio).
| Model | Scenario | Supported Tiers | Pixel Range |
| ------------------ | ------------------------------ | :--------------: | -------------------- |
| `wan2.7-image-pro` | Text-to-image (non-sequential) | 1K / **2K** / 4K | 768×768 \~ 4096×4096 |
| `wan2.7-image-pro` | Editing / sequential | 1K / **2K** | 768×768 \~ 2048×2048 |
| `wan2.7-image` | All scenarios | 1K / **2K** | 768×768 \~ 2048×2048 |
Negative prompt describing elements to avoid. Example: `"blurry, distorted, low quality"`
Whether to add an "AI Generated" watermark to the bottom-right corner.
Random seed, range 0–2147483647. Same seed with identical parameters produces visually consistent results.
Enable enhanced reasoning mode to improve image quality at the cost of longer generation time.
Only effective when **sequential mode is disabled** and **no image input** is provided.
Enable **sequential image generation** mode — generates multiple thematically coherent images in one request. Ideal for storyboards and series.
* Maximum `n` is 12 when enabled
* `thinking_mode` and `color_palette` are ignored in sequential mode
* `wan2.7-image-pro` supports up to 2K in sequential mode (4K not supported)
Bounding boxes for interactive editing — specifies exact regions to edit or insert content.
**Structure:** `[[[x1, y1, x2, y2], ...], ...]`
* Outer array length must equal the length of `image_urls`
* Pass `[]` for images with no bounding box
* Max 2 boxes per image; coordinates are absolute pixel values, origin (0,0) at top-left
Example: `[[], [[989, 515, 1138, 681]]]`
Custom color theme. **Standard mode only** (not sequential mode).
* 3–10 entries (8 recommended); each entry requires `hex` and `ratio`
* All `ratio` values must sum to exactly `100.00%`
```json theme={null}
[
{ "hex": "#C2D1E6", "ratio": "23.51%" },
{ "hex": "#636574", "ratio": "76.49%" }
]
```
## Response
Response status. Returns `"success"` on success.
Unique task identifier used to query generation results.
Initial task status, always `processing` upon submission.
## Examples
### Text-to-Image (minimal)
```json theme={null}
{
"model": "wan2.7-image-pro",
"prompt": "A flower shop with exquisite windows, beautiful wooden door, flowers on display"
}
```
### Text-to-Image (with resolution)
```json theme={null}
{
"model": "wan2.7-image-pro",
"prompt": "Summer beach, blue sky and white clouds, 4K ultra HD",
"size": "4K",
"thinking_mode": true
}
```
### Text-to-Image (custom color palette)
```json theme={null}
{
"model": "wan2.7-image-pro",
"prompt": "Minimalist modern living room",
"size": "2K",
"color_palette": [
{ "hex": "#C2D1E6", "ratio": "23.51%" },
{ "hex": "#CDD8E9", "ratio": "20.13%" },
{ "hex": "#B5C8DB", "ratio": "15.88%" },
{ "hex": "#C0B5B4", "ratio": "13.27%" },
{ "hex": "#DAE0EC", "ratio": "10.11%" },
{ "hex": "#636574", "ratio": "8.93%" },
{ "hex": "#CACAD2", "ratio": "5.55%" },
{ "hex": "#CBD4E4", "ratio": "2.62%" }
]
}
```
### Sequential Image Generation
```json theme={null}
{
"model": "wan2.7-image-pro",
"prompt": "Cinematic series: the same stray orange cat, consistent features. First: under cherry blossoms in spring. Second: old street shade in summer. Third: fallen leaves in autumn. Fourth: snow footprints in winter.",
"enable_sequential": true,
"n": 4,
"size": "2K"
}
```
### Single Image Editing
```json theme={null}
{
"model": "wan2.7-image",
"prompt": "Replace the background with a sunset scene, warm color tones",
"image_urls": ["https://example.com/portrait.jpg"],
"size": "2K"
}
```
### Multi-Image Reference / Element Fusion
```json theme={null}
{
"model": "wan2.7-image-pro",
"prompt": "Apply the graffiti from image 2 onto the car in image 1",
"image_urls": [
"https://example.com/car.webp",
"https://example.com/paint.webp"
],
"size": "2K"
}
```
### Interactive Editing (Bounding Box)
`bbox_list` corresponds 1-to-1 with `image_urls`. Pass `[]` for images with no selection.
```json theme={null}
{
"model": "wan2.7-image-pro",
"prompt": "Place the alarm clock from image 1 into the selected area of image 2, blending naturally",
"image_urls": [
"https://example.com/clock.webp",
"https://example.com/desk.webp"
],
"bbox_list": [
[],
[[989, 515, 1138, 681]]
],
"size": "2K"
}
```
**Querying Results**
Image generation is asynchronous. Poll the [Task Status](/en/api-reference/tasks/status) endpoint using the returned `task_id` until `status == completed`.
# Z-Image-Turbo Image Generation
Source: https://docs.apimart.ai/en/api-reference/images/z-image-turbo/generation
POST https://api.apimart.ai/v1/images/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Lightweight and fast image generation, supports Chinese and English
- Supports 1K/2K resolution tiers, supports smart prompt rewriting
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "z-image-turbo",
"prompt": "Ink painting style landscape scenery"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"model": "z-image-turbo",
"prompt": "Ink painting style landscape scenery"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
model: "z-image-turbo",
prompt: "Ink painting style landscape scenery",
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JGXYZ1234567890ABCDEF"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance, please top up",
"type": "payment_required"
}
}
```
## Supported Models
| Model | Description | Images Per Request | Pricing |
| --------------- | ------------------------------------------------------------------- | ------------------ | ----------- |
| `z-image-turbo` | Lightweight and fast image generation, supports Chinese and English | Fixed 1 image | Fixed price |
## Authorizations
All endpoints require Bearer Token authentication
Get API Key:
Visit [API Key Management](https://apimart.ai/keys) to get your API Key
Add to request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Model name
* `z-image-turbo` - Lightweight and fast image generation, supports Chinese and English
Whether to run content moderation before submitting the image task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for image generation, up to 800 characters
Image aspect ratio
Supported aspect ratios:
* `1:1` - Square (default)
* `4:3` - Landscape 4:3
* `3:4` - Portrait 3:4
* `16:9` - Landscape widescreen
* `9:16` - Portrait vertical
* `3:2` - Landscape 3:2
* `2:3` - Portrait 2:3
Resolution tier
* `1K` - Standard resolution (default)
* `2K` - High definition resolution
Smart prompt rewriting
When enabled, AI will automatically optimize the prompt for better results, and costs will increase.
* `false` - Disabled (default)
* `true` - Enabled
## Resolution Reference Table
Output size is controlled by the combination of `size` (ratio) + `resolution` (resolution tier).
| Ratio | 1K Tier | 2K Tier |
| ------ | --------- | --------- |
| `1:1` | 1024×1024 | 2048×2048 |
| `4:3` | 1152×864 | 2048×1536 |
| `3:4` | 864×1152 | 1536×2048 |
| `16:9` | 1280×720 | 2048×1152 |
| `9:16` | 720×1280 | 1152×2048 |
| `3:2` | 1248×832 | 2048×1360 |
| `2:3` | 832×1248 | 1360×2048 |
## Usage Examples
**Basic Text-to-Image (minimal request)**
```json theme={null}
{
"model": "z-image-turbo",
"prompt": "Ink painting style landscape scenery"
}
```
**Specify ratio and resolution**
```json theme={null}
{
"model": "z-image-turbo",
"prompt": "Minimalist style cafe interior design",
"size": "16:9",
"resolution": "2K"
}
```
**Enable smart prompt rewriting**
```json theme={null}
{
"model": "z-image-turbo",
"prompt": "A cat",
"prompt_extend": true
}
```
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Task unique identifier
## Notes
1. **Asynchronous Processing**: After submission, a `task_id` is returned. Poll `/v1/tasks/{task_id}` to get results
2. **Image Storage**: Generated images are mirrored to platform CDN and are valid long-term
3. **Billing Rules**: Billed per successfully generated image, no charge for failures
4. **Fixed Count**: Z-Image-Turbo generates exactly 1 image per request, `n` parameter is not supported
# Gemini Context Caching Guide
Source: https://docs.apimart.ai/en/api-reference/texts/gemini/context-cache
Create and reuse Gemini context caches (Context Cache) through the OpenAI-compatible Chat Completions API or the native Gemini API. Use cache_control to cache stable prefixes and reduce token costs for repeated long content.
This guide explains how to create and reuse Gemini context caches (Context Cache) through the OpenAI-compatible Chat Completions API or the native Gemini API.
Before you begin:
```bash theme={null}
export API_KEY="YOUR_API_KEY"
```
The examples in this guide use `gemini-3.6-flash`. Refer to the platform's model documentation and pricing page to confirm whether other models support Context Cache.
## Use cases
When multiple requests repeatedly include the same large body of content, you can cache the stable prefix. Examples include:
* A very long system prompt
* A fixed knowledge base or product documentation
* Stable conversation history in a multi-turn conversation
* Reused tool definitions and instructions
Context Cache is ideal for requests where the content at the beginning remains unchanged while the final question changes.
## Core usage
Add `cache_control` to the content block in the last message of the stable prefix:
```json theme={null}
{
"type": "text",
"text": "This is the final section of the stable prefix",
"cache_control": {
"type": "ephemeral",
"ttl": "5m"
}
}
```
Supported TTL values:
| TTL | Meaning |
| ---- | ------------------- |
| `5m` | Cache for 5 minutes |
| `1h` | Cache for 1 hour |
If `ttl` is omitted, it defaults to `5m`.
## Message structure
We recommend the following structure:
```text theme={null}
system
→ Stable long-form text or message history
→ Stable prefix boundary with cache_control
→ Current user question (not cached)
```
The message containing `cache_control` and all messages before it form the cached prefix. At least one real-time message must follow it.
## OpenAI-compatible request example
```bash theme={null}
curl "https://api.apimart.ai/v1/chat/completions" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.6-flash",
"stream": false,
"messages": [
{
"role": "system",
"content": "Answer questions strictly based on the provided reference material."
},
{
"role": "user",
"content": "Place the long reference material you want to reuse here..."
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I have read and understood the reference material above.",
"cache_control": {
"type": "ephemeral",
"ttl": "5m"
}
}
]
},
{
"role": "user",
"content": "Summarize the three main points in the reference material."
}
]
}'
```
On the first request, the system attempts to create a cache and uses the new cache to complete that same request.
You do not need to call a separate cache creation endpoint. `cache_control` specifies both the cache boundary and the cache lifetime.
## Native Gemini request example
The native Gemini `generateContent` endpoint also supports adding `cache_control` to `contents[].parts[]`:
```bash theme={null}
curl "https://api.apimart.ai/v1beta/models/gemini-3.6-flash:generateContent" \
-H "x-goog-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"systemInstruction": {
"parts": [
{
"text": "Answer questions strictly based on the provided reference material."
}
]
},
"contents": [
{
"role": "user",
"parts": [
{
"text": "Place the long reference material you want to reuse here..."
}
]
},
{
"role": "model",
"parts": [
{
"text": "I have read and understood the reference material above.",
"cache_control": {
"type": "ephemeral",
"ttl": "5m"
}
}
]
},
{
"role": "user",
"parts": [
{
"text": "Summarize the three main points in the reference material."
}
]
}
]
}'
```
`cache_control` is a platform extension to the Gemini request format. After identifying the boundary, the platform removes this field before forwarding the request and automatically creates or reuses cached content (`cachedContent`).
The streaming endpoint uses the same request body. You only need to change the URL to:
```bash theme={null}
curl -N "https://api.apimart.ai/v1beta/models/gemini-3.6-flash:streamGenerateContent?alt=sse" \
-H "x-goog-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Place the long reference material you want to reuse here...",
"cache_control": {
"type": "ephemeral",
"ttl": "5m"
}
}
]
},
{
"role": "user",
"parts": [
{
"text": "Summarize the three main points in the reference material."
}
]
}
]
}'
```
When reusing the cache, keep `systemInstruction`, the `contents` before the boundary, the TTL, and tools unchanged. Only modify the real-time content after the boundary.
## Creation and reuse flow
When you send a request with `cache_control` for the first time:
```text theme={null}
Identify the stable prefix
→ Create Context Cache
→ Reference the new cache in the current request
→ Return the model response
```
When you send the same stable prefix again:
```text theme={null}
Identify the same stable prefix
→ Reuse the unexpired Context Cache
→ Send only the current real-time content
→ Return the model response
```
As a result, the first request may already report a large number of cache-hit tokens. This is expected and does not require a separate warm-up request.
## Reusing a cache
For subsequent requests, keep the following unchanged:
* The model
* All messages before `cache_control`
* `cache_control.ttl`
* Tool definitions (if you use tools)
* `systemInstruction` in native Gemini requests
Only modify the real-time question after the boundary:
```json theme={null}
{
"role": "user",
"content": "What risks are mentioned in the reference material?"
}
```
The system reuses the existing cache as long as the stable prefix is identical and the cache has not expired.
The following changes create a different cache:
* Changing text or message order within the stable prefix
* Changing the model
* Changing `5m` to `1h`
* Changing tools or tool parameter definitions
* Using a different API user or channel
## Python example
```python theme={null}
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.apimart.ai/v1",
)
stable_messages = [
{
"role": "system",
"content": "Answer questions strictly based on the provided reference material.",
},
{
"role": "user",
"content": "Place the long reference material you want to reuse here...",
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I have read and understood the reference material above.",
"cache_control": {
"type": "ephemeral",
"ttl": "5m",
},
}
],
},
]
response = client.chat.completions.create(
model="gemini-3.6-flash",
messages=[
*stable_messages,
{
"role": "user",
"content": "Summarize the three main points in the reference material.",
},
],
)
print(response.choices[0].message.content)
print(response.usage)
```
For subsequent requests, reuse the same `stable_messages` and replace only the final user message.
## Checking for a cache hit
### OpenAI-compatible response
Check the following fields in the response:
```json theme={null}
{
"usage": {
"prompt_tokens": 14430,
"prompt_tokens_details": {
"cached_tokens": 14420,
"cache_write_tokens": 0
}
}
}
```
Field descriptions:
| Field | Meaning |
| -------------------- | ------------------------------------------------- |
| `prompt_tokens` | All input tokens for this request |
| `cached_tokens` | Input tokens read from the cache for this request |
| `cache_write_tokens` | Cache-write tokens; a value of `0` is expected |
The first request may also report a large `cached_tokens` value because the system can create a cache and reference it within the same model call.
### Native Gemini response
Check `usageMetadata.cachedContentTokenCount` in the response:
```json theme={null}
{
"usageMetadata": {
"promptTokenCount": 13926,
"cachedContentTokenCount": 13916,
"totalTokenCount": 13954
}
}
```
Field descriptions:
| Field | Meaning |
| ------------------------- | ------------------------------------------------- |
| `promptTokenCount` | All input tokens for this request |
| `cachedContentTokenCount` | Input tokens read from the cache for this request |
| `totalTokenCount` | Total input and output tokens for this request |
`streamGenerateContent` returns the same `usageMetadata` in an SSE response frame. The client should read the frame containing this field rather than checking only the first text frame.
## Recommendations
1. Cache only long content that is truly stable and will be reused multiple times.
2. Place the question that changes with each request after the `cache_control` boundary.
3. Do not include timestamps, random IDs, or dynamic user information in the stable prefix.
4. Use `5m` when you expect repeated calls within a short period.
5. Use `1h` when you need a longer reuse window.
6. If the prefix is too short, the model does not support caching, or the cache is temporarily unavailable, the request may automatically run in standard mode.
7. For native Gemini requests, the cache boundary must be placed in `contents[].parts[]`, not in `systemInstruction`.
## Frequently asked questions
Yes. `generateContent` and `streamGenerateContent` use the same `cache_control` structure. The boundary must be placed in `contents[].parts[]`, and at least one real-time content item must remain after the content containing the boundary.
If the request explicitly provides a native `cachedContent` resource name, the platform prioritizes the user-provided resource and does not create a cache automatically.
Common reasons include:
* The stable prefix does not exactly match the previous request
* The TTL has expired
* The model or tools were changed
* The cached content does not meet the model's minimum token requirement
* `cache_control` was placed on the final message, leaving no real-time question after it
This is not recommended. The final message is usually the current real-time question and should not be cached. If no real-time message follows the boundary, the request runs in standard mode.
No. Currently, only `5m` and `1h` are supported. Any other value returns HTTP 400.
Yes, but all boundaries must use the same TTL, and the system uses the final boundary. In general, using only one boundary per request is recommended for a clearer structure.
Usually not. If the conditions for creating or reusing a cache are not met, the system automatically sends a standard request. Parameter errors such as an invalid TTL or mixed TTL values are exceptions.
The request automatically runs in standard mode without creating an explicit cache or incurring cache storage fees. Standard input, output, and any available implicit caching continue to be billed according to the model's existing rules.
This is expected behavior for Gemini context caching. Cache creation costs are recorded as separate cache storage fees rather than using OpenAI/Claude-style `cache_write_tokens` to represent the amount written to the cache.
Not necessarily. The system may also produce implicit cache hits. For regular users, cache-read tokens indicate whether the current request benefited from cache reads. To verify explicit cache creation fees, check the Context Cache storage entries in the platform's usage logs.
Creating a cache may incur a one-time cache storage fee. When the cache is used, hit tokens are billed at the cache-read price. Refer to the model pricing displayed on the platform for exact rates.
# Gemini Native Format
Source: https://docs.apimart.ai/en/api-reference/texts/gemini/quickstart
POST https://api.apimart.ai/v1beta/models/{model}:{method}
- Call Gemini models using Google Native API format
- Synchronous processing mode with real-time response
- Minimal parameters for quick start
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1beta/models/gemini-2.5-pro:generateContent \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Hello, please introduce yourself"
}
]
}
]
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1beta/models/gemini-2.5-pro:generateContent"
payload = {
"contents": [
{
"role": "user",
"parts": [
{
"text": "Hello, please introduce yourself"
}
]
}
]
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1beta/models/gemini-2.5-pro:generateContent";
const payload = {
contents: [
{
role: "user",
parts: [
{
text: "Hello, please introduce yourself"
}
]
}
]
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1beta/models/gemini-2.5-pro:generateContent"
payload := map[string]interface{}{
"contents": []map[string]interface{}{
{
"role": "user",
"parts": []map[string]interface{}{
{
"text": "Hello, please introduce yourself",
},
},
},
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1beta/models/gemini-2.5-pro:generateContent";
String payload = """
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Hello, please introduce yourself"
}
]
}
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
[
[
"role" => "user",
"parts" => [
[
"text" => "Hello, please introduce yourself"
]
]
]
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1beta/models/gemini-2.5-pro:generateContent")
payload = {
contents: [
{
role: "user",
parts: [
{
text: "Hello, please introduce yourself"
}
]
}
]
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```json 200 theme={null}
{
"code": 200,
"data": {
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "Hello! I'm pleased to introduce myself.\n\nI am a large language model, trained and developed by Google..."
}
]
},
"finishReason": "STOP",
"index": 0,
"safetyRatings": [
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE"
}
]
}
],
"promptFeedback": {
"safetyRatings": [
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE"
}
]
]
},
"usageMetadata": {
"promptTokenCount": 4,
"candidatesTokenCount": 611,
"totalTokenCount": 2422,
"thoughtsTokenCount": 1807,
"promptTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 4
}
]
}
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"status": "INVALID_ARGUMENT"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API Key",
"status": "UNAUTHENTICATED"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance, please recharge",
"status": "PAYMENT_REQUIRED"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access denied",
"status": "PERMISSION_DENIED"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Model not found",
"status": "NOT_FOUND"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded, please try again later",
"status": "RESOURCE_EXHAUSTED"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error",
"status": "INTERNAL"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway, service temporarily unavailable",
"status": "BAD_GATEWAY"
}
}
```
```json 503 theme={null}
{
"error": {
"code": 503,
"message": "Service temporarily unavailable",
"status": "UNAVAILABLE"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Path Parameters
Model name
The examples use `gemini-2.5-pro`, which you can replace with other supported Gemini models:
* `gemini-3.5-flash` - Gemini 3.5 Flash
* `gemini-3.1-pro-preview` - Gemini 3.1 Pro Preview
* `gemini-3-pro-preview` - Gemini 3 Pro Preview
* `gemini-2.5-pro` - Gemini 2.5 Pro
Generation method (recommended: `generateContent` for quick start):
* `generateContent`: Wait for complete response and return at once
* `streamGenerateContent`: Stream response, return content in chunks
Available options: `generateContent`, `streamGenerateContent`
## Body
List of conversation contents
Minimum 1 message required
Role type:
* `user`: User message
* `model`: Model response (used in conversation history)
Message content parts
Text content
Inline data (for multimodal input)
MIME type, e.g. `image/jpeg`, `image/png`
Base64 encoded data
Example:
```json theme={null}
[
{
"role": "user",
"parts": [{ "text": "Hello, please introduce yourself" }]
}
]
```
Generation configuration (optional)
Controls output randomness, range 0.0-2.0
* Lower values make output more deterministic
* Higher values make output more random
Default: 1.0
Maximum number of tokens to generate
Different models have different maximum limits
Nucleus sampling parameter, range 0.0-1.0
Controls the probability mass considered during sampling
Top-K sampling parameter
Sample only from the K most probable tokens at each step
List of stop sequences
Stop generation when these sequences are encountered
Safety settings (optional)
Safety category:
* `HARM_CATEGORY_HATE_SPEECH`: Hate speech
* `HARM_CATEGORY_DANGEROUS_CONTENT`: Dangerous content
* `HARM_CATEGORY_HARASSMENT`: Harassment
* `HARM_CATEGORY_SEXUALLY_EXPLICIT`: Sexually explicit content
Threshold level:
* `BLOCK_NONE`: Don't block
* `BLOCK_ONLY_HIGH`: Block only high risk
* `BLOCK_MEDIUM_AND_ABOVE`: Block medium and above risk
* `BLOCK_LOW_AND_ABOVE`: Block low and above risk
## Response
List of candidate responses
Generated content
Role, typically `model`
List of content parts
Generated text content
Finish reason:
* `STOP`: Normal completion
* `MAX_TOKENS`: Maximum token limit reached
* `SAFETY`: Stopped for safety reasons
* `RECITATION`: Stopped due to recitation
* `OTHER`: Other reasons
Index of the candidate response
List of safety ratings
Safety category
Probability level: `NEGLIGIBLE`, `LOW`, `MEDIUM`, `HIGH`
Prompt feedback information
Safety ratings for the prompt
Block reason (if prompt was blocked)
Usage statistics
Number of tokens in the prompt
Number of tokens in candidate responses
Total number of tokens consumed
Number of tokens used for thinking (if applicable)
Prompt token details
Modality type: `TEXT`, `IMAGE`, etc.
Number of tokens for this modality
# General Chat API (Default Streaming)
Source: https://docs.apimart.ai/en/api-reference/texts/general/chat-completions
POST https://api.apimart.ai/v1/chat/completions
- Unified chat API interface supporting all text generation models
- Select different AI models via the model parameter
- Compatible with OpenAI Chat Completions API format
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/chat/completions \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gpt-5", # Can be replaced with any supported model ID
"messages": [
{
"role": "system",
"content": "You are a professional AI assistant."
},
{
"role": "user",
"content": "Tell me about the history of artificial intelligence."
}
]
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/chat/completions"
payload = {
"model": "gpt-5", # Can be replaced with any supported model ID
"messages": [
{
"role": "system",
"content": "You are a professional AI assistant."
},
{
"role": "user",
"content": "Tell me about the history of artificial intelligence."
}
]
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/chat/completions";
const payload = {
model: "gpt-5", // Can be replaced with any supported model ID
messages: [
{
role: "system",
content: "You are a professional AI assistant."
},
{
role: "user",
content: "Tell me about the history of artificial intelligence."
}
]
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/chat/completions"
payload := map[string]interface{}{
"model": "gpt-5", // Can be replaced with any supported model ID
"messages": []map[string]string{
{
"role": "system",
"content": "You are a professional AI assistant.",
},
{
"role": "user",
"content": "Tell me about the history of artificial intelligence.",
},
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/chat/completions";
// Can be replaced with any supported model ID
String payload = """
{
"model": "gpt-5",
"messages": [
{
"role": "system",
"content": "You are a professional AI assistant."
},
{
"role": "user",
"content": "Tell me about the history of artificial intelligence."
}
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"gpt-5",
"messages" => [
[
"role" => "system",
"content" => "You are a professional AI assistant."
],
[
"role" => "user",
"content" => "Tell me about the history of artificial intelligence."
]
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/chat/completions")
# Can be replaced with any supported model ID
payload = {
model: "gpt-5",
messages: [
{
role: "system",
content: "You are a professional AI assistant."
},
{
role: "user",
content: "Tell me about the history of artificial intelligence."
}
]
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/chat/completions")!
let payload: [String: Any] = [
"model": "gpt-5", // Can be replaced with any supported model ID
"messages": [
[
"role": "system",
"content": "You are a professional AI assistant."
],
[
"role": "user",
"content": "Tell me about the history of artificial intelligence."
]
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/chat/completions";
// Can be replaced with any supported model ID
var payload = @"{
""model"": ""gpt-5"",
""messages"": [
{
""role"": ""system"",
""content"": ""You are a professional AI assistant.""
},
{
""role"": ""user"",
""content"": ""Tell me about the history of artificial intelligence.""
}
]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/chat/completions";
// Can be replaced with any supported model ID
const char *payload = "{"
"\"model\":\"gpt-5\","
"\"messages\":[{\"role\":\"system\",\"content\":\"You are a professional AI assistant.\"},{\"role\":\"user\",\"content\":\"Tell me about the history of artificial intelligence.\"}]"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/chat/completions"];
NSDictionary *payload = @{
@"model": @"gpt-5", // Can be replaced with any supported model ID
@"messages": @[
@{
@"role": @"system",
@"content": @"You are a professional AI assistant."
},
@{
@"role": @"user",
@"content": @"Tell me about the history of artificial intelligence."
}
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/chat/completions"
(* Can be replaced with any supported model ID *)
let payload = {|{
"model": "gpt-5",
"messages": [
{
"role": "system",
"content": "You are a professional AI assistant."
},
{
"role": "user",
"content": "Tell me about the history of artificial intelligence."
}
]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/chat/completions');
// Can be replaced with any supported model ID
final payload = {
'model': 'gpt-5',
'messages': [
{
'role': 'system',
'content': 'You are a professional AI assistant.'
},
{
'role': 'user',
'content': 'Tell me about the history of artificial intelligence.'
}
]
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/chat/completions"
# Can be replaced with any supported model ID
payload <- list(
model = "gpt-5",
messages = list(
list(
role = "system",
content = "You are a professional AI assistant."
),
list(
role = "user",
content = "Tell me about the history of artificial intelligence."
)
)
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": {
"id": "chatcmpl-9876543210",
"object": "chat.completion",
"created": 1677652288,
"model": "gpt-5",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The history of artificial intelligence (AI) dates back to the 1950s...\n\n1. **Early Period (1950s-1960s)**: The proposal of the Turing Test marked the beginning of AI research...\n\n2. **Expert Systems Era (1970s-1980s)**: Rule-based systems began to be applied in medical diagnosis, financial analysis, and other fields...\n\n3. **Rise of Machine Learning (1990s-2000s)**: Statistical learning methods gradually became mainstream...\n\n4. **Deep Learning Revolution (2010s-Present)**: Breakthroughs in neural network technology brought explosive growth to AI..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 28,
"completion_tokens": 320,
"total_tokens": 348
}
}
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please recharge",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway, service temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Model name
Supported models include:
* **OpenAI**: `gpt-5`, `gpt-5.1`, `gpt-5-chat-latest`, `gpt-5-mini`
* **Anthropic**: `claude-opus-4-8`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-opus-4-5-20251101`
* **Google**: `gemini-3.5-flash`, `gemini-3.1-pro-preview`, `gemini-3-pro-preview`, `gemini-3-pro-preview-thinking`, `gemini-3-flash-preview`, `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.5-flash-lite`
* **DeepSeek**: `deepseek-v4-pro`, `deepseek-v4-flash`, `deepseek-v3.2`, `deepseek-v3.2-exp`, `deepseek-r1-250528`, `deepseek-v3-0324`
* More models being added continuously...
List of conversation messages
Message array. Each message contains `role` and `content` fields.
**💡 Quick fill (Try it area):**
1. Click "+ Add an item" to add a message
2. Enter `user` (user message), `assistant` (AI response), or `system` (system prompt) for `role`
3. Enter what you want to say in `content`
Role type
* `user` - User message
* `assistant` - AI response (for multi-turn)
* `system` - System prompt
Message content
Your question or message
**Example:**
```json theme={null}
[{"role": "user", "content": "Hello, please introduce yourself"}]
```
**Advanced usage:**
Add system prompt (to define AI behavior):
```json theme={null}
[
{"role": "system", "content": "You are a professional Python tutor"},
{"role": "user", "content": "How do I learn programming?"}
]
```
Multi-turn conversation (with context):
```json theme={null}
[
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi! How can I help you?"},
{"role": "user", "content": "Tell me about AI"}
]
```
**Role descriptions:**
* `user`: User message (use this most of the time)
* `system`: System prompt to set AI behavior and role
* `assistant`: AI's previous responses, used for conversation context
Controls output randomness, range 0-2
* Lower values (e.g., 0.2) make output more deterministic
* Higher values (e.g., 1.8) make output more random
Default: 1.0
Maximum number of tokens to generate
Different models have different maximum limits, please refer to specific model documentation
Whether to use streaming output
* `true`: Streaming response (SSE format)
* `false`: Complete response at once
Default: true
Nucleus sampling parameter, range 0-1
Controls diversity of generated text, recommend using either this or temperature
Default: 1.0
Frequency penalty, range -2.0 to 2.0
Positive values reduce the likelihood of repeating the same words
Default: 0
Presence penalty, range -2.0 to 2.0
Positive values increase the likelihood of talking about new topics
Default: 0
Stop sequences
Up to 4 sequences where generation will stop when encountered
Number of completions to generate
Default: 1
**⚠️ Note:** Must enter a plain number (e.g., `1`), do not use quotes or it will cause an error
## Response
Unique identifier for the response
Object type, fixed as `chat.completion`
Creation timestamp
The actual model name used
List of generated responses
Choice index
Message content
Role type (assistant)
Generated text content
Reason for completion
Possible values:
* `stop` - Natural completion
* `length` - Maximum length reached
* `content_filter` - Content filtered
* `function_call` - Function call
Token usage statistics
Number of tokens in the input messages
Number of tokens in the generated content
Total number of tokens
## Supported Models
### OpenAI Series
* `gpt-5` - GPT-5 base model
* `gpt-5.1` - GPT-5.1 enhanced version
* `gpt-5-chat-latest` - GPT-5 latest chat version
* `gpt-5-mini` - GPT-5 lightweight version, cost-effective
### Anthropic Series
* `claude-opus-4-8` - Claude Opus 4.8 flagship model
* `claude-opus-4-7` - Claude Opus 4.7 flagship model
* `claude-opus-4-6` - Claude Opus 4.6 flagship model
* `claude-sonnet-4-6` - Claude Sonnet 4.6 balanced version
* `claude-opus-4-5-20251101` - Claude Opus 4.5 model
### Google Series
* `gemini-3.5-flash` - Gemini 3.5 fast version
* `gemini-3.1-pro-preview` - Gemini 3.1 Pro preview version
* `gemini-3-pro-preview` - Gemini 3 Pro preview version
* `gemini-3-pro-preview-thinking` - Gemini 3 Pro deep thinking preview version
* `gemini-3-flash-preview` - Gemini 3 Flash preview version
* `gemini-2.5-pro` - Gemini 2.5 professional version
* `gemini-2.5-flash` - Gemini 2.5 fast version
* `gemini-2.5-flash-lite` - Gemini 2.5 ultra-lightweight version
### DeepSeek Series
* `deepseek-v4-pro` - DeepSeek V4 professional version
* `deepseek-v4-flash` - DeepSeek V4 fast version
* `deepseek-v3.2` - DeepSeek V3.2 standard version
* `deepseek-v3.2-exp` - DeepSeek V3.2 experimental version
* `deepseek-r1-250528` - DeepSeek R1 reasoning model
* `deepseek-v3-0324` - DeepSeek V3 standard version
## Usage Examples
### Basic Conversation
```json theme={null}
{
"model": "gpt-5",
"messages": [
{"role": "user", "content": "Hello"}
]
}
```
### System Prompt
```json theme={null}
{
"model": "claude-sonnet-4-6",
"messages": [
{"role": "system", "content": "You are a professional Python programming tutor"},
{"role": "user", "content": "How to use list comprehensions?"}
]
}
```
### Multi-turn Conversation
```json theme={null}
{
"model": "gemini-2.5-flash",
"messages": [
{"role": "user", "content": "What is machine learning?"},
{"role": "assistant", "content": "Machine learning is a branch of artificial intelligence..."},
{"role": "user", "content": "Can you give me an example?"}
]
}
```
### Streaming Output
```json theme={null}
{
"model": "gpt-5",
"messages": [
{"role": "user", "content": "Write a poem about spring"}
],
"stream": true
}
```
# General Chat API (Default Non-Streaming)
Source: https://docs.apimart.ai/en/api-reference/texts/general/chat-completions-nostream
POST https://api.apimart.ai/api/v1/chat/completions
- Unified chat API interface supporting all text generation models
- Select different AI models via the model parameter
- Compatible with OpenAI Chat Completions API format
- Non-streaming output, returns complete response at once
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/api/v1/chat/completions \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gpt-5", # Can be replaced with any supported model ID
"stream": false,
"messages": [
{
"role": "system",
"content": "You are a professional AI assistant."
},
{
"role": "user",
"content": "Tell me about the history of artificial intelligence."
}
]
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/api/v1/chat/completions"
payload = {
"model": "gpt-5", # Can be replaced with any supported model ID
"stream": False,
"messages": [
{
"role": "system",
"content": "You are a professional AI assistant."
},
{
"role": "user",
"content": "Tell me about the history of artificial intelligence."
}
]
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/api/v1/chat/completions";
const payload = {
model: "gpt-5", // Can be replaced with any supported model ID
stream: false,
messages: [
{
role: "system",
content: "You are a professional AI assistant."
},
{
role: "user",
content: "Tell me about the history of artificial intelligence."
}
]
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/api/v1/chat/completions"
payload := map[string]interface{}{
"model": "gpt-5", // Can be replaced with any supported model ID
"stream": false,
"messages": []map[string]string{
{
"role": "system",
"content": "You are a professional AI assistant.",
},
{
"role": "user",
"content": "Tell me about the history of artificial intelligence.",
},
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/api/v1/chat/completions";
// Can be replaced with any supported model ID
String payload = """
{
"model": "gpt-5",
"stream": false,
"messages": [
{
"role": "system",
"content": "You are a professional AI assistant."
},
{
"role": "user",
"content": "Tell me about the history of artificial intelligence."
}
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"gpt-5",
"stream" => false,
"messages" => [
[
"role" => "system",
"content" => "You are a professional AI assistant."
],
[
"role" => "user",
"content" => "Tell me about the history of artificial intelligence."
]
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/api/v1/chat/completions")
# Can be replaced with any supported model ID
payload = {
model: "gpt-5",
stream: false,
messages: [
{
role: "system",
content: "You are a professional AI assistant."
},
{
role: "user",
content: "Tell me about the history of artificial intelligence."
}
]
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/api/v1/chat/completions")!
let payload: [String: Any] = [
"model": "gpt-5", // Can be replaced with any supported model ID
"stream": false,
"messages": [
[
"role": "system",
"content": "You are a professional AI assistant."
],
[
"role": "user",
"content": "Tell me about the history of artificial intelligence."
]
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/api/v1/chat/completions";
// Can be replaced with any supported model ID
var payload = @"{
""model"": ""gpt-5"",
""stream"": false,
""messages"": [
{
""role"": ""system"",
""content"": ""You are a professional AI assistant.""
},
{
""role"": ""user"",
""content"": ""Tell me about the history of artificial intelligence.""
}
]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/api/v1/chat/completions";
// Can be replaced with any supported model ID
const char *payload = "{"
"\"model\":\"gpt-5\","
"\"stream\":false,"
"\"messages\":[{\"role\":\"system\",\"content\":\"You are a professional AI assistant.\"},{\"role\":\"user\",\"content\":\"Tell me about the history of artificial intelligence.\"}]"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/api/v1/chat/completions"];
NSDictionary *payload = @{
@"model": @"gpt-5", // Can be replaced with any supported model ID
@"stream": @NO,
@"messages": @[
@{
@"role": @"system",
@"content": @"You are a professional AI assistant."
},
@{
@"role": @"user",
@"content": @"Tell me about the history of artificial intelligence."
}
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/api/v1/chat/completions"
(* Can be replaced with any supported model ID *)
let payload = {|{
"model": "gpt-5",
"stream": false,
"messages": [
{
"role": "system",
"content": "You are a professional AI assistant."
},
{
"role": "user",
"content": "Tell me about the history of artificial intelligence."
}
]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/api/v1/chat/completions');
// Can be replaced with any supported model ID
final payload = {
'model': 'gpt-5',
'stream': false,
'messages': [
{
'role': 'system',
'content': 'You are a professional AI assistant.'
},
{
'role': 'user',
'content': 'Tell me about the history of artificial intelligence.'
}
]
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/api/v1/chat/completions"
# Can be replaced with any supported model ID
payload <- list(
model = "gpt-5",
stream = FALSE,
messages = list(
list(
role = "system",
content = "You are a professional AI assistant."
),
list(
role = "user",
content = "Tell me about the history of artificial intelligence."
)
)
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": {
"id": "chatcmpl-9876543210",
"object": "chat.completion",
"created": 1677652288,
"model": "gpt-5",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The history of artificial intelligence (AI) dates back to the 1950s...\n\n1. **Early Period (1950s-1960s)**: The proposal of the Turing Test marked the beginning of AI research...\n\n2. **Expert Systems Era (1970s-1980s)**: Rule-based systems began to be applied in medical diagnosis, financial analysis, and other fields...\n\n3. **Rise of Machine Learning (1990s-2000s)**: Statistical learning methods gradually became mainstream...\n\n4. **Deep Learning Revolution (2010s-Present)**: Breakthroughs in neural network technology brought explosive growth to AI..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 28,
"completion_tokens": 320,
"total_tokens": 348
}
}
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please recharge",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway, service temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Model name
Supported models include:
* **OpenAI**: `gpt-5`, `gpt-5.1`, `gpt-5-chat-latest`, `gpt-5-mini`
* **Anthropic**: `claude-opus-4-8`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-opus-4-5-20251101`
* **Google**: `gemini-3.5-flash`, `gemini-3.1-pro-preview`, `gemini-3-pro-preview`, `gemini-3-pro-preview-thinking`, `gemini-3-flash-preview`, `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.5-flash-lite`
* **DeepSeek**: `deepseek-v4-pro`, `deepseek-v4-flash`, `deepseek-v3.2`, `deepseek-v3.2-exp`, `deepseek-r1-250528`, `deepseek-v3-0324`
* More models being added continuously...
List of conversation messages
Message array. Each message contains `role` and `content` fields.
**💡 Quick fill (Try it area):**
1. Click "+ Add an item" to add a message
2. Enter `user` (user message), `assistant` (AI response), or `system` (system prompt) for `role`
3. Enter what you want to say in `content`
Role type
* `user` - User message
* `assistant` - AI response (for multi-turn)
* `system` - System prompt
Message content
Your question or message
**Example:**
```json theme={null}
[{"role": "user", "content": "Hello, please introduce yourself"}]
```
**Advanced usage:**
Add system prompt (to define AI behavior):
```json theme={null}
[
{"role": "system", "content": "You are a professional Python tutor"},
{"role": "user", "content": "How do I learn programming?"}
]
```
Multi-turn conversation (with context):
```json theme={null}
[
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi! How can I help you?"},
{"role": "user", "content": "Tell me about AI"}
]
```
**Role descriptions:**
* `user`: User message (use this most of the time)
* `system`: System prompt to set AI behavior and role
* `assistant`: AI's previous responses, used for conversation context
Controls output randomness, range 0-2
* Lower values (e.g., 0.2) make output more deterministic
* Higher values (e.g., 1.8) make output more random
Default: 1.0
Maximum number of tokens to generate
Different models have different maximum limits, please refer to specific model documentation
Whether to use streaming output
* `false`: Complete response at once
* `true`: Streaming return
Default: false
Nucleus sampling parameter, range 0-1
Controls diversity of generated text, recommend using either this or temperature
Default: 1.0
Frequency penalty, range -2.0 to 2.0
Positive values reduce the likelihood of repeating the same words
Default: 0
Presence penalty, range -2.0 to 2.0
Positive values increase the likelihood of talking about new topics
Default: 0
Stop sequences
Up to 4 sequences where generation will stop when encountered
Number of completions to generate
Default: 1
**⚠️ Note:** Must enter a plain number (e.g., `1`), do not use quotes or it will cause an error
## Response
Unique identifier for the response
Object type, fixed as `chat.completion`
Creation timestamp
The actual model name used
List of generated responses
Choice index
Message content
Role type (assistant)
Generated text content
Reason for completion
Possible values:
* `stop` - Natural completion
* `length` - Maximum length reached
* `content_filter` - Content filtered
* `function_call` - Function call
Token usage statistics
Number of tokens in the input messages
Number of tokens in the generated content
Total number of tokens
## Supported Models
### OpenAI Series
* `gpt-5` - GPT-5 base model
* `gpt-5.1` - GPT-5.1 enhanced version
* `gpt-5-chat-latest` - GPT-5 latest chat version
* `gpt-5-mini` - GPT-5 lightweight version, cost-effective
### Anthropic Series
* `claude-opus-4-8` - Claude Opus 4.8 flagship model
* `claude-opus-4-7` - Claude Opus 4.7 flagship model
* `claude-opus-4-6` - Claude Opus 4.6 flagship model
* `claude-sonnet-4-6` - Claude Sonnet 4.6 balanced version
* `claude-opus-4-5-20251101` - Claude Opus 4.5 model
### Google Series
* `gemini-3.5-flash` - Gemini 3.5 fast version
* `gemini-3.1-pro-preview` - Gemini 3.1 Pro preview version
* `gemini-3-pro-preview` - Gemini 3 Pro preview version
* `gemini-3-pro-preview-thinking` - Gemini 3 Pro deep thinking preview version
* `gemini-3-flash-preview` - Gemini 3 Flash preview version
* `gemini-2.5-pro` - Gemini 2.5 professional version
* `gemini-2.5-flash` - Gemini 2.5 fast version
* `gemini-2.5-flash-lite` - Gemini 2.5 ultra-lightweight version
### DeepSeek Series
* `deepseek-v4-pro` - DeepSeek V4 professional version
* `deepseek-v4-flash` - DeepSeek V4 fast version
* `deepseek-v3.2` - DeepSeek V3.2 standard version
* `deepseek-v3.2-exp` - DeepSeek V3.2 experimental version
* `deepseek-r1-250528` - DeepSeek R1 reasoning model
* `deepseek-v3-0324` - DeepSeek V3 standard version
## Usage Examples
### Basic Conversation
```json theme={null}
{
"model": "gpt-5",
"stream": false,
"messages": [
{"role": "user", "content": "Hello"}
]
}
```
### System Prompt
```json theme={null}
{
"model": "claude-sonnet-4-6",
"stream": false,
"messages": [
{"role": "system", "content": "You are a professional Python programming tutor"},
{"role": "user", "content": "How to use list comprehensions?"}
]
}
```
### Multi-turn Conversation
```json theme={null}
{
"model": "gemini-2.5-flash",
"stream": false,
"messages": [
{"role": "user", "content": "What is machine learning?"},
{"role": "assistant", "content": "Machine learning is a branch of artificial intelligence..."},
{"role": "user", "content": "Can you give me an example?"}
]
}
```
# Claude Context Caching Guide
Source: https://docs.apimart.ai/en/api-reference/texts/general/claude-context-cache
Cache reusable prompt prefixes through the Claude Messages API or the OpenAI-compatible Chat Completions API to reduce token costs from repeatedly processing long content.
Claude context caching (Context Cache) is designed for reusing long prefixes such as system prompts, documents, codebases, or conversation history. Add `cache_control` to a stable prefix so that the first request creates a cache and subsequent requests can read the unexpired cache.
Before you begin, set your API key:
```bash theme={null}
export API_KEY="YOUR_API_KEY"
```
The examples in this guide use `claude-sonnet-5`. Refer to the platform's model documentation to confirm whether other models support context caching.
## Use cases
When multiple requests repeatedly include the same large body of content, you can cache a stable prefix, such as:
* A long system prompt
* A fixed knowledge base or product documentation
* Conversation history that remains unchanged across a multi-turn conversation
* Reused codebases, tool definitions, and instructions
Context caching is ideal for requests where the content at the beginning remains unchanged while the final question keeps changing.
## Claude Messages API
### 5-minute cache
Add `cache_control` to the content block you want to cache:
```bash theme={null}
curl "https://api.apimart.ai/v1/messages" \
-H "x-api-key: $API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"system": [
{
"type": "text",
"text": "Place the long prefix you want to reuse here...",
"cache_control": {
"type": "ephemeral"
}
}
],
"messages": [
{
"role": "user",
"content": "Answer the question based on the content above."
}
]
}'
```
`system` must be an array of content blocks. A string-form `system` cannot include `cache_control`.
If `ttl` is omitted, the cache lifetime defaults to 5 minutes.
### 1-hour cache
To use a 1-hour cache, add the `anthropic-beta` request header and set `ttl` to `1h`:
```bash theme={null}
curl "https://api.apimart.ai/v1/messages" \
-H "x-api-key: $API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: extended-cache-ttl-2025-04-11" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"system": [
{
"type": "text",
"text": "Place the long prefix you want to reuse here...",
"cache_control": {
"type": "ephemeral",
"ttl": "1h"
}
}
],
"messages": [
{
"role": "user",
"content": "Answer the question based on the content above."
}
]
}'
```
Supported TTL values:
| TTL | Meaning |
| ---- | ------------------------------------------------------------------------------------ |
| `5m` | Cache for 5 minutes; this value is used when `ttl` is omitted |
| `1h` | Cache for 1 hour; the corresponding `anthropic-beta` request header is also required |
### Response usage fields
The Claude Messages API reports regular input, cache-write, and cache-read tokens separately in `usage`:
```json theme={null}
{
"usage": {
"input_tokens": 23,
"cache_creation_input_tokens": 2619,
"cache_read_input_tokens": 0,
"cache_creation": {
"ephemeral_5m_input_tokens": 2619,
"ephemeral_1h_input_tokens": 0
},
"output_tokens": 24
}
}
```
Calculate total input tokens as follows:
```text theme={null}
input_tokens
+ cache_creation_input_tokens
+ cache_read_input_tokens
```
These three values do not overlap. The first request usually has `cache_creation_input_tokens > 0`. When you send the same stable prefix again, you should see `cache_read_input_tokens > 0`.
## OpenAI-compatible API
### Request example
When using caching through `/v1/chat/completions`, the `cache_control` structure is similar to the Claude Messages API:
```bash theme={null}
curl "https://api.apimart.ai/v1/chat/completions" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"messages": [
{
"role": "system",
"content": [
{
"type": "text",
"text": "Place the long prefix you want to reuse here...",
"cache_control": {
"type": "ephemeral"
}
}
]
},
{
"role": "user",
"content": "Answer the question based on the content above."
}
]
}'
```
### 1-hour cache
The OpenAI-compatible format also supports 1-hour caching. Add the `anthropic-beta` request header and set `ttl: "1h"` in `cache_control`:
```bash theme={null}
-H "anthropic-beta: extended-cache-ttl-2025-04-11"
```
```json theme={null}
"cache_control": {
"type": "ephemeral",
"ttl": "1h"
}
```
### `content` must be an array
In the OpenAI-compatible format, `cache_control` must be placed in a specific content block. It cannot be attached to a string-form message.
```json theme={null}
{
"role": "system",
"content": "Place the long prefix here...",
"cache_control": {
"type": "ephemeral"
}
}
```
The structure above does not enable caching, and the request does not return an error. Use the following structure instead:
```json theme={null}
{
"role": "system",
"content": [
{
"type": "text",
"text": "Place the long prefix here...",
"cache_control": {
"type": "ephemeral"
}
}
]
}
```
If `content` is a string, the cache marker is ignored and the input is processed as regular input. Check the cache usage fields in the response to confirm whether the cache was hit.
### Cache user or assistant content blocks
You can also add `cache_control` to a content block in a `user` or `assistant` message to cache a long document or a multi-turn conversation prefix:
```json theme={null}
{
"role": "user",
"content": [
{
"type": "text",
"text": "Place the long document you want to reuse here...",
"cache_control": {
"type": "ephemeral"
}
},
{
"type": "text",
"text": "Summarize the three main points in the document above."
}
]
}
```
Split the stable content and the current question into separate content blocks, and add `cache_control` only to the stable content block.
### Response usage fields
The OpenAI-compatible format uses different fields to report cache usage:
```json theme={null}
{
"usage": {
"prompt_tokens": 1942,
"completion_tokens": 22,
"prompt_tokens_details": {
"cached_tokens": 1921,
"cache_write_tokens": 0
},
"claude_cache_creation_5_m_tokens": 0,
"claude_cache_creation_1_h_tokens": 0
}
}
```
Field mapping:
| Meaning | Claude Messages API | OpenAI-compatible API |
| ------------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------- |
| Total input | Sum of the three input fields | `prompt_tokens` |
| Cache read | `cache_read_input_tokens` | `prompt_tokens_details.cached_tokens` |
| General cache-write field | `cache_creation_input_tokens` | `prompt_tokens_details.cache_write_tokens` (only populated when no TTL breakdown is available) |
| 5-minute cache write | `cache_creation.ephemeral_5m_input_tokens` | `claude_cache_creation_5_m_tokens` |
| 1-hour cache write | `cache_creation.ephemeral_1h_input_tokens` | `claude_cache_creation_1_h_tokens` |
| Output | `output_tokens` | `completion_tokens` |
If `prompt_tokens_details.cache_write_tokens` is `0`, also check `claude_cache_creation_5_m_tokens` and `claude_cache_creation_1_h_tokens`. When TTL-specific fields are available, the cache-write amount is returned in the corresponding field.
The numbers and units in `claude_cache_creation_5_m_tokens` and `claude_cache_creation_1_h_tokens` are separated by underscores. Use the field names exactly as returned in the response.
The OpenAI-compatible endpoint may return an SSE streaming response even when you do not explicitly pass `stream: true`. Clients should support parsing `chat.completion.chunk`; usage is included in the final data chunk that contains `usage`.
## Conditions for a cache hit
### The prefix meets the minimum length
For the model used in these examples, the cache prefix usually needs to be at least approximately 1024 tokens. If the prefix is too short, the cache marker may be ignored without an error.
### The prefix remains byte-identical
The text, spaces, line breaks, and content-block order in the cache prefix must remain identical. Do not add timestamps, random IDs, request counters, or other dynamic content to the stable prefix.
### The request does not trigger a model refusal
If the request triggers a model refusal, the response may still report cache-creation tokens, but that cache is not read on the next request. When troubleshooting a cache miss, also check whether `stop_reason` is `refusal`.
### The cache is still valid
The cache lifetime is 5 minutes or 1 hour and is calculated from the most recent access. A cache hit refreshes the lifetime.
## Billing usage
Cache-related usage falls into three categories:
| Usage | When it occurs |
| ------------- | ---------------------------------------- |
| Cache write | When the cache is first created |
| Cache read | When a subsequent request hits the cache |
| Regular input | Input outside the cached prefix |
The three categories do not overlap. Cache writes usually cost more than regular input, while cache reads usually cost less. Context caching is therefore best suited to stable prefixes that will be reused within the TTL.
## Minimal reproducible example
The script below generates a sufficiently long stable prefix and sends the same request twice in succession. The second response should have `cache_read_input_tokens > 0`.
```bash theme={null}
python3 - <<'PY' > /tmp/claude-cache-request.json
import json
paragraph = (
"Prompt caching stores a prefix of the request so that later requests "
"can reuse the same byte-identical prefix without processing it again. "
)
system_text = (
"You are a documentation assistant. Reference material follows.\n\n"
+ paragraph * 40
)
print(json.dumps({
"model": "claude-sonnet-5",
"max_tokens": 32,
"system": [{
"type": "text",
"text": system_text,
"cache_control": {"type": "ephemeral"}
}],
"messages": [{
"role": "user",
"content": "In one sentence, what must remain unchanged?"
}]
}))
PY
for request_number in 1 2; do
echo "Request ${request_number}"
curl -s "https://api.apimart.ai/v1/messages" \
-H "x-api-key: $API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
--data @/tmp/claude-cache-request.json \
| python3 -c "import json, sys; print(json.load(sys.stdin)['usage'])"
done
```
Expected result:
```text theme={null}
Request 1: cache_creation_input_tokens > 0, cache_read_input_tokens = 0
Request 2: cache_creation_input_tokens = 0, cache_read_input_tokens > 0
```
## Troubleshooting checklist
If the cache is not hit, check the following in order:
* Whether `stop_reason` is `refusal`
* Whether the cache prefix meets the model's minimum token requirement
* Whether the stable prefix is byte-identical across both requests
* Whether `content` is an array in the OpenAI-compatible format
* Whether `cache_control` is placed in a specific content block
* Whether a 1-hour cache includes both `ttl: "1h"` and the corresponding `anthropic-beta` request header
* Whether the cache has exceeded its TTL
* Whether you are reading the cache usage fields for the endpoint you are using
# Claude Messages API
Source: https://docs.apimart.ai/en/api-reference/texts/general/claude-messages
POST https://api.apimart.ai/v1/messages
- Fully compatible with the native Anthropic Claude Messages protocol (`POST /v1/messages`)
- Supports multi-turn conversations, streaming SSE, tool use, and extended thinking
- Supports multimodal content including text and images
- Responses are upstream passthrough with no `{code, data}` wrapper
**Do not mix the two APIs**: `/v1/*` is the inference API (this document — upstream passthrough, no wrapper); `/api/*` is the management API (balance/logs, etc., response shape `{success, message, data}`). If you see docs claiming `/v1/messages` returns `{code, data}`, this document takes precedence.
```bash cURL theme={null}
curl https://api.apimart.ai/v1/messages \
-H "x-api-key: $API_KEY" \
-H "anthropic-version: 2025-10-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello, world"}
]
}'
```
```python Python theme={null}
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.apimart.ai"
)
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello, world"}
]
)
print(message.content)
```
```javascript JavaScript theme={null}
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.API_KEY,
baseURL: 'https://api.apimart.ai'
});
const message = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages: [
{ role: 'user', content: 'Hello, world' }
]
});
console.log(message.content);
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
url := "https://api.apimart.ai/v1/messages"
payload := map[string]interface{}{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": []map[string]string{
{
"role": "user",
"content": "Hello, world",
},
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("x-api-key", os.Getenv("API_KEY"))
req.Header.Set("anthropic-version", "2025-10-01")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/messages";
String apiKey = System.getenv("API_KEY");
String payload = """
{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Hello, world"
}
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("x-api-key", apiKey)
.header("anthropic-version", "2025-10-01")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"claude-sonnet-4-6",
"max_tokens" => 1024,
"messages" => [
[
"role" => "user",
"content" => "Hello, world"
]
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"x-api-key: " . $apiKey,
"anthropic-version: 2025-10-01",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/messages")
api_key = ENV['API_KEY']
payload = {
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [
{
role: "user",
content: "Hello, world"
}
]
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = api_key
request["anthropic-version"] = "2025-10-01"
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/messages")!
let apiKey = ProcessInfo.processInfo.environment["API_KEY"] ?? ""
let payload: [String: Any] = [
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
[
"role": "user",
"content": "Hello, world"
]
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
request.setValue("2025-10-01", forHTTPHeaderField: "anthropic-version")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/messages";
var apiKey = Environment.GetEnvironmentVariable("API_KEY");
var payload = @"{
""model"": ""claude-sonnet-4-6"",
""max_tokens"": 1024,
""messages"": [
{
""role"": ""user"",
""content"": ""Hello, world""
}
]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", apiKey);
client.DefaultRequestHeaders.Add("anthropic-version", "2025-10-01");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
const char *api_key = getenv("API_KEY");
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/messages";
const char *payload = "{"
"\"model\":\"claude-sonnet-4-6\","
"\"max_tokens\":1024,"
"\"messages\":[{\"role\":\"user\",\"content\":\"Hello, world\"}]"
"}";
char auth_header[256];
snprintf(auth_header, sizeof(auth_header), "x-api-key: %s", api_key);
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, auth_header);
headers = curl_slist_append(headers, "anthropic-version: 2025-10-01");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/messages"];
NSString *apiKey = [NSProcessInfo processInfo].environment[@"API_KEY"];
NSDictionary *payload = @{
@"model": @"claude-sonnet-4-6",
@"max_tokens": @1024,
@"messages": @[
@{
@"role": @"user",
@"content": @"Hello, world"
}
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:apiKey forHTTPHeaderField:@"x-api-key"];
[request setValue:@"2025-10-01" forHTTPHeaderField:@"anthropic-version"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/messages"
let api_key = Sys.getenv "API_KEY"
let payload = {|{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Hello, world"
}
]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "x-api-key" api_key
|> fun h -> Header.add h "anthropic-version" "2025-10-01"
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/messages');
final apiKey = Platform.environment['API_KEY'];
final payload = {
'model': 'claude-sonnet-4-6',
'max_tokens': 1024,
'messages': [
{
'role': 'user',
'content': 'Hello, world'
}
]
};
final response = await http.post(
url,
headers: {
'x-api-key': apiKey!,
'anthropic-version': '2025-10-01',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/messages"
api_key <- Sys.getenv("API_KEY")
payload <- list(
model = "claude-sonnet-4-6",
max_tokens = 1024,
messages = list(
list(
role = "user",
content = "Hello, world"
)
)
)
response <- POST(
url,
add_headers(
`x-api-key` = api_key,
`anthropic-version` = "2025-10-01",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"model": "claude-sonnet-4-6",
"id": "msg_011CdfeHuC728oxqaLrRNbcB",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Hello! I'm Claude. Nice to meet you."
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"stop_details": null,
"usage": {
"input_tokens": 12,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 0
},
"output_tokens": 18,
"service_tier": "standard",
"inference_geo": "global"
}
}
```
```json 400 theme={null}
{
"error": {
"code": "model_not_found",
"message": "model not found (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": "",
"message": "Invalid API key (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": "",
"message": "Insufficient balance (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": "",
"message": "Too many requests (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": "",
"message": "Internal server error (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
```
## Authorizations
Authentication supports two methods — **use either one**:
Anthropic-style API key header
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
```
x-api-key: YOUR_API_KEY
```
Bearer token authentication (alternative to `x-api-key`)
```
Authorization: Bearer YOUR_API_KEY
```
API version (**optional** — requests work without it)
Recommended for easier future migration to Anthropic's official endpoint:
Example: `2025-10-01`
## Body
Model name
* `claude-opus-4-8` - Claude Opus 4.8 flagship model
* `claude-opus-4-7` - Claude Opus 4.7 flagship model
* `claude-opus-4-6` - Claude Opus 4.6 flagship model
* `claude-sonnet-4-6` - Claude Sonnet 4.6 balanced version
* `claude-opus-4-5-20251101` - Claude Opus 4.5 model
List of messages
Array of messages for the model to generate the next response. Each message contains `role` and `content` fields.
**💡 Quick fill (Try it area):**
1. Click "+ Add an item" to add a message
2. `role` input: `user` (user message) or `assistant` (AI response, for multi-turn)
3. `content` input: your message text
Role type
Options: `user` (user message), `assistant` (AI response, for multi-turn conversations and prefilling)
Note: Claude API uses a separate `system` parameter for system prompts, not in messages
Message content
Text content of the message
**Single user message:**
```json theme={null}
[{"role": "user", "content": "Hello, Claude"}]
```
**Multi-turn conversation:**
```json theme={null}
[
{"role": "user", "content": "Hello there."},
{"role": "assistant", "content": "Hi, I'm Claude. How can I help you?"},
{"role": "user", "content": "Can you explain LLMs in plain English?"}
]
```
**Prefilled assistant response:**
```json theme={null}
[
{"role": "user", "content": "What's the Greek name for Sun? (A) Sol (B) Helios (C) Sun"},
{"role": "assistant", "content": "The best answer is ("}
]
```
Maximum tokens to generate (**required**, same as Anthropic official)
Maximum number of tokens to generate before stopping. The model may stop before reaching this limit.
Different models have different maximum values. See model docs. Minimum: 1
Extended thinking configuration
When enabled, the response `content` may include `thinking` blocks. **Prefer** the standard model name plus this parameter over platform-side `-thinking` model aliases, so you can migrate to the official endpoint without code changes.
If multi-turn conversations need to pass thinking blocks back, you must return the `signature` **unchanged**, or the upstream will reject the request.
System prompt
System prompts set Claude's role, personality, goals, and instructions.
**String format:**
```json theme={null}
{
"system": "You are a professional Python programming tutor"
}
```
**Structured format:**
```json theme={null}
{
"system": [
{
"type": "text",
"text": "You are a professional Python programming tutor"
}
]
}
```
Temperature parameter, range 0-1
Controls randomness of output:
* Low values (e.g., 0.2): More deterministic, conservative
* High values (e.g., 0.8): More random, creative
Default: 1.0
Nucleus sampling parameter, range 0-1
Uses nucleus sampling. Recommend using either `temperature` or `top_p`, not both.
Default: 1.0
Top-K sampling
Sample from top K options only, removes "long tail" low probability responses.
Recommended for advanced use cases only.
Enable streaming
When `true`, uses Server-Sent Events (SSE) to stream responses.
Default: false
Stop sequences
Custom text sequences that cause the model to stop generating.
Maximum 4 sequences.
Example: `["\n\nHuman:", "\n\nAssistant:"]`
Metadata
Metadata object for the request.
Includes:
* `user_id`: User identifier
Tool definitions
List of tools the model can use to complete tasks.
**Function tool example:**
```json theme={null}
{
"tools": [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["location"]
}
}
]
}
```
Supported tool types:
* Custom function tools
* Computer use tool (computer\_20241022)
* Text editor tool (text\_editor\_20241022)
* Bash tool (bash\_20241022)
Tool choice strategy
Controls how the model uses tools:
* `{"type": "auto"}`: Auto-decide (default)
* `{"type": "any"}`: Must use a tool
* `{"type": "tool", "name": "tool_name"}`: Use specific tool
## Response
Unique message identifier
Example: `"msg_013Zva2CMHLNnXjNJJKqJ2EF"`
Object type
Always `"message"`
Role
Always `"assistant"`
Content blocks array
`content` is an array of blocks distinguished by `type`. **A single response may contain multiple blocks** (for example, with thinking enabled: a `thinking` block plus a `text` block).
**text block:**
```json theme={null}
{ "type": "text", "text": "OK" }
```
**tool\_use block:**
```json theme={null}
{
"type": "tool_use",
"id": "toolu_01QgsazxKXSfQVj9Q1XxjYXo",
"name": "get_weather",
"input": { "city": "Beijing" },
"caller": { "type": "direct" }
}
```
`caller` is a newer upstream field not yet documented officially; ignore it when parsing.
**thinking block** (present when the request body includes the `thinking` parameter):
```json theme={null}
{
"type": "thinking",
"thinking": "Reasoning process text...",
"signature": ""
}
```
When returning thinking blocks in multi-turn conversations, you must pass `signature` back **unchanged**, or the upstream will reject the request.
**Do not assume `content[0]` is text.** With thinking enabled, `content[0]` may be a thinking block. Iterate and filter:
```python theme={null}
text = "".join(b.text for b in resp.content if b.type == "text")
```
Model that handled the request
Example: `"claude-sonnet-4-6"`
Stop reason
Possible values:
* `end_turn`: Natural completion
* `max_tokens`: Reached maximum tokens
* `stop_sequence`: Hit stop sequence
* `tool_use`: Invoked a tool
Stop sequence triggered
The stop sequence that was generated, if any; otherwise `null`
Newer Anthropic field; `null` for typical requests
Token usage statistics (full structure for non-streaming)
Number of input tokens
Number of output tokens (**already includes** thinking tokens; do not double-count for billing)
Cache write tokens
Cache hit tokens
`{ ephemeral_5m_input_tokens, ephemeral_1h_input_tokens }`
e.g. `"standard"`
e.g. `"global"`
May appear when thinking is enabled: `{ thinking_tokens: int }`
## Usage Examples
### Basic Conversation
```python theme={null}
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.apimart.ai"
)
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "Explain quantum computing basics"}
]
)
print(message.content[0].text)
```
### Multi-turn Conversation
```python theme={null}
messages = [
{"role": "user", "content": "What is machine learning?"},
{"role": "assistant", "content": "Machine learning is a branch of AI..."},
{"role": "user", "content": "Can you give a practical example?"}
]
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=messages
)
```
### Using System Prompts
```python theme={null}
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system="You are a senior Python developer expert in code review and optimization.",
messages=[
{"role": "user", "content": "How to optimize this code?\n\n[code]"}
]
)
```
### Streaming Response
```python theme={null}
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "Write a short essay about AI"}
]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
```
### Tool Use
```python theme={null}
tools = [
{
"name": "get_stock_price",
"description": "Get real-time stock price",
"input_schema": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "Stock ticker symbol, e.g., AAPL"
}
},
"required": ["ticker"]
}
}
]
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=[
{"role": "user", "content": "What's Tesla's stock price?"}
]
)
# Handle tool calls
if message.stop_reason == "tool_use":
tool_use = next(block for block in message.content if block.type == "tool_use")
print(f"Calling tool: {tool_use.name}")
print(f"Arguments: {tool_use.input}")
```
### Vision Understanding
```python theme={null}
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "url",
"url": "https://example.com/image.jpg"
}
},
{
"type": "text",
"text": "Describe this image"
}
]
}
]
)
```
### Base64 Image
```python theme={null}
import base64
with open("image.jpg", "rb") as image_file:
image_data = base64.b64encode(image_file.read()).decode("utf-8")
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": image_data
}
},
{
"type": "text",
"text": "Analyze this image"
}
]
}
]
)
```
## Best Practices
### 1. Prompt Engineering
**Clear role definition:**
```python theme={null}
system = """You are an experienced data scientist specializing in:
- Statistical analysis and data visualization
- Machine learning model development
- Python and R programming
Provide professional, accurate advice."""
```
**Structured output:**
```python theme={null}
message = "Please return the analysis results in JSON format with summary, key_findings, and recommendations fields."
```
### 2. Error Handling
```python theme={null}
from anthropic import APIError, RateLimitError
try:
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}]
)
except RateLimitError:
print("Rate limit exceeded, please retry later")
except APIError as e:
print(f"API error: {e}")
```
### 3. Token Optimization
```python theme={null}
# Use shorter prompts
messages = [
{"role": "user", "content": "Summarize key points:\n\n[long text]"}
]
# Limit output length
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=500, # Limit output
messages=messages
)
```
### 4. Prefilling Responses
```python theme={null}
# Guide model to specific format
messages = [
{"role": "user", "content": "List 5 Python best practices"},
{"role": "assistant", "content": "Here are 5 Python best practices:\n\n1."}
]
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=messages
)
```
## Streaming Response Handling
### Python Streaming
```python theme={null}
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.apimart.ai"
)
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "Write a Python decorator example"}
]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
```
### JavaScript Streaming
```javascript theme={null}
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.API_KEY,
baseURL: 'https://api.apimart.ai'
});
const stream = await client.messages.stream({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages: [
{ role: 'user', content: 'Write a React component example' }
]
});
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta' &&
chunk.delta.type === 'text_delta') {
process.stdout.write(chunk.delta.text);
}
}
```
## Platform Differences & Integration Notes
### Unwrapped response
Successful `POST /v1/messages` responses **return the Anthropic message object directly**, with **no** `{code, data}` wrapper. This is required for 1:1 compatibility with official SDKs, Claude Code, Cline, and similar tools.
### Error format (only real incompatibility with official)
```json theme={null}
{
"error": {
"code": "model_not_found",
"message": "... (request id: ...)",
"param": "",
"type": "apimart_error"
}
}
```
Compared with Anthropic official: missing top-level `"type": "error"`; `error.type` is always `apimart_error`, not semantic types like `invalid_request_error`.
**Integration guidance**: do not branch retries on `error.type`; use **HTTP status + `error.code`** instead:
| Status | Meaning | Suggested action |
| ------ | ---------------------- | ---------------------------------- |
| 400 | Bad request parameters | Do not retry; fix the request body |
| 401 | Invalid key | Do not retry |
| 402 | Insufficient balance | Do not retry; prompt top-up |
| 429 | Rate limited | Retry with backoff |
| 5xx | Upstream/gateway error | Retry with exponential backoff |
When reporting issues, include the request id at the end of `error.message` and the response header `x-oneapi-request-id`.
### Streaming SSE
Send `"stream": true`. Event sequence matches official:
`message_start` → `content_block_start` → `ping` → `content_block_delta` (multiple) → `content_block_stop` → `message_delta` → `message_stop`
⚠️ **Stream vs non-stream `usage` differs**: `message_delta.usage` typically has only 4 token fields and **does not** include `cache_creation`, `service_tier`, or `inference_geo`. Parse them separately or treat all as optional.
### Unimplemented endpoint
`POST /v1/messages/count_tokens` is **not implemented and returns 404**. Official SDK `client.messages.count_tokens()` will fail. Estimate tokens locally, or read `usage.input_tokens` from responses.
### Ignore unknown fields
This endpoint passes through upstream fields. Anthropic may add fields at any time (e.g. `stop_details`, `inference_geo`, `caller`, `output_tokens_details`). Do not use strict schemas:
* Go: do not use `DisallowUnknownFields()`
* Pydantic: do not use `extra="forbid"`
* TypeScript / Zod: use `.passthrough()` instead of `.strict()`
### Model name recommendation
Same-name models with a `-thinking` suffix are platform extension aliases. **Prefer** the standard model name without the suffix plus the request-body `thinking` parameter for easier migration to the official endpoint.
Other request-body fields match official: `model`, `messages`, `max_tokens` (required), `system`, `temperature`, `top_p`, `top_k`, `stop_sequences`, `stream`, `tools`, `tool_choice`, `thinking`, `metadata`. Semantics follow the [Anthropic Messages API](https://docs.anthropic.com/en/api/messages).
## Important Notes
1. **API Key Security**:
* Store API keys in environment variables
* Never hardcode keys in source code
* Rotate keys regularly
2. **Rate Limiting**:
* Be aware of API rate limits
* Implement retry mechanisms (by HTTP status code)
* Use exponential backoff
3. **Token Management**:
* Monitor token usage (read `usage`)
* Optimize prompt length
* Use appropriate `max_tokens` values
* With thinking enabled, `output_tokens` already includes thinking tokens — do not double-count for billing
4. **Model Selection**:
* Opus: Complex tasks, deep thinking required
* Sonnet: Balanced performance and cost
* Haiku: Fast response, simple tasks
5. **Content parsing**:
* Iterate `content` for `type == "text"`; do not hardcode `content[0].text`
* If the model returns JSON wrapped in Markdown code fences, that is model output — not an API wrapper (see FAQ below)
6. **Content Filtering**:
* Validate user input
* Filter sensitive information
* Implement content moderation
## FAQ
### The response `content` text is a ` ```json ... ``` ` code fence — how do I strip it?
This is not an API structure issue. The `text` field holds the **raw model-generated content**: if the model decides you want JSON, it may wrap it in a Markdown code fence. The API does not and should not rewrite model output.
To get clean structured data, use one of these three approaches (recommended from highest to lowest reliability):
1. **Use tools to force structured output** — most reliable; the `input` field is already a parsed object:
```json theme={null}
{
"tools": [{
"name": "emit_result",
"input_schema": {
"type": "object",
"properties": { "answer": { "type": "string" } }
}
}],
"tool_choice": { "type": "tool", "name": "emit_result" }
}
```
2. **Prefill the assistant message** so the model continues from `{`:
```json theme={null}
{
"messages": [
{ "role": "user", "content": "..." },
{ "role": "assistant", "content": "{" }
]
}
```
3. In the system prompt, explicitly require “output JSON only, with no Markdown code fences.”
Do not rely on regex to strip code fences — parsing will break when the model occasionally omits the fence.
# Models List Metadata API
Source: https://docs.apimart.ai/en/api-reference/texts/models/list
GET https://api.apimart.ai/v1/models
- GET /v1/models — basic list
- + `expand` query parameter to include category, capability tags, and parameter schema
- For automation, dynamic forms, pre-validation
The **model list metadata endpoint** (`GET /v1/models`) returns only basic fields such as the model name by default. Adding the `expand` query parameter appends the following metadata to each model:
* **Category** (`category`): `chat` / `image` / `video` / `audio`
* **Capability tags** (`capability_tags`): such as `Text to Video` and `Image to Image`
* **Parameter schema** (`parameters`): standard JSON Schema indicating required/optional, enums, ranges, and defaults
Use it to fetch the full catalog once and generate client code, build parameter forms dynamically, or validate requests locally before sending them.
> **Backward compatible**: Without `expand` (or with an unrecognized value), the response is identical to the existing format, so existing clients are unaffected.
**Model scope**: The returned models are controlled by the API key's model restrictions and assigned group. `category=unknown` means that the platform has not yet cataloged the model's category metadata.
## Get model list (with metadata)
**GET** `/v1/models`
### Request headers
```
Authorization: Bearer YOUR_API_KEY
```
### Query parameters
| Parameter | Type | Required | Description |
| ---------- | ------ | :------: | ----------------------------------------------------------------------------------------------------------------------------- |
| `expand` | string | No | `category` adds category and capability tags (lightweight); `parameters` adds full JSON Schema (full payload, large response) |
| `category` | string | No | Filter by category: `chat` / `image` / `video` / `audio` / `unknown`. Only effective when `expand` is provided. |
The returned model scope is the same as when `expand` is omitted: it is controlled by the API key's model restrictions and assigned group.
### Example 1: Just category
```bash cURL theme={null}
curl -s "https://api.apimart.ai/v1/models?expand=category" \
-H "Authorization: Bearer YOUR_API_KEY"
```
```json theme={null}
{
"success": true,
"object": "list",
"data": [
{
"id": "wan2.6",
"object": "model",
"created": 1626777600,
"owned_by": "alibaba",
"supported_endpoint_types": ["openai"],
"category": "video",
"capability_tags": ["Text to Video"]
},
{
"id": "gpt-4o",
"object": "model",
"created": 1626777600,
"owned_by": "openai",
"supported_endpoint_types": ["openai"],
"category": "chat",
"capability_tags": ["Text", "Vision"]
}
]
}
```
### Example 2: Full parameter contract for video models
```bash cURL theme={null}
curl -s "https://api.apimart.ai/v1/models?expand=parameters&category=video" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept-Encoding: gzip" --compressed
```
Single item (`input_schema.properties` shows only selected fields):
```json theme={null}
{
"id": "wan2.6",
"object": "model",
"created": 1626777600,
"owned_by": "alibaba",
"supported_endpoint_types": ["openai"],
"category": "video",
"capability_tags": ["Text to Video"],
"parameters": {
"operation": "video_generation",
"method": "POST",
"endpoint": "/v1/videos/generations",
"schema_version": "2026-07-30",
"source": "task_model_registry",
"input_schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": true,
"required": ["model"],
"anyOf": [
{ "required": ["prompt"] },
{ "required": ["messages"] },
{ "required": ["image_urls"] },
{ "required": ["image_with_roles"] },
{ "required": ["video_urls"] }
],
"properties": {
"model": { "type": "string", "const": "wan2.6" },
"prompt": { "type": "string", "minLength": 1 },
"duration": { "type": "integer", "minimum": 1 },
"resolution": { "type": "string" },
"aspect_ratio": { "type": "string" }
}
}
}
}
```
## Response field description
### Item fields
| Field | Type | Condition | Description |
| --------------------------------------------------------------------- | --------- | ---------------------------------------- | ------------------------------------------------ |
| `id` / `object` / `created` / `owned_by` / `supported_endpoint_types` | - | Always | Same as legacy interface |
| `category` | string | With `expand` | `chat` / `image` / `video` / `audio` / `unknown` |
| `capability_tags` | string\[] | With `expand` and tags | See capability tags table |
| `parameters` | object | `expand=parameters` and contract present | See parameters block |
`category=unknown` indicates the platform has not yet cataloged metadata for that model (usually non-standard names configured in the Key's whitelist). The model itself can still be called normally.
### Capability tags
| Category | Possible tags |
| -------- | --------------------------------------------------- |
| video | `Text to Video`, `Image to Video`, `Video to Video` |
| image | `Text to Image`, `Image to Image` |
| chat | `Text`, `Embedding`, `Vision`, `Audio`, `Omni` |
| audio | `Audio` |
### parameters block
| Field | Description |
| --------------------- | ------------------------------------------------------------------------------ |
| `operation` | `image_generation` / `video_generation` |
| `method` + `endpoint` | HTTP method and path the model should use (e.g. `POST /v1/videos/generations`) |
| `schema_version` | Contract version (date); fields only add, never remove |
| `source` | Contract source for debugging; `base` means only generic base contract |
| `input_schema` | JSON Schema draft 2020-12 — full request body contract |
### How to read input\_schema
Standard JSON Schema. Most tooling (ajv, pydantic, openapi-generator, etc.) can consume it directly:
* **Required parameters** = the top-level `required` array; `anyOf` means “at least one of the following combinations” (in the example above, choose one of `prompt`, `messages`, or the three reference-media inputs)
* **Enum values** = `enum` on properties
* **Range** = `minimum` / `maximum`
* **Default** = `default`
* `additionalProperties: true` — allows extra fields not listed in the schema (typically passed via `metadata`)
## Query a single model
In addition to the list, single-model contracts have a dedicated endpoint (same shape, with extra idempotency and response contract explanation blocks):
```bash theme={null}
curl -s "https://api.apimart.ai/v1/models/wan2.6/schema" \
-H "Authorization: Bearer YOUR_API_KEY"
# For model names containing "/", use the query-parameter form
curl -s "https://api.apimart.ai/v1/model-schema?model=provider/model-name" \
-H "Authorization: Bearer YOUR_API_KEY"
```
## Notes
1. **Chat / audio models currently only have `category` and `capability_tags`, with no `parameters`** (parameter contracts currently cover image / video only and will be added for other categories in later versions).
2. **The schema is a best-effort contract; server-side validation is authoritative**: some dynamic constraints, such as specific resolution and duration combinations, may not be fully expressed in the schema. The server may still reject a request and return a specific reason.
3. **Data freshness is measured in minutes**: the catalog is cached, so newly added models or parameter changes may take a few minutes to appear.
4. **A full `expand=parameters` response can reach hundreds of KB**: filter by `category` when possible and send `Accept-Encoding: gzip`.
5. This parameter only affects OpenAI-format model lists; Anthropic / Gemini dialect model lists do not support `expand`.
# OpenAI Multimodal Responses API
Source: https://docs.apimart.ai/en/api-reference/texts/openai/responses
POST https://api.apimart.ai/v1/responses
- Fully compatible with OpenAI Responses API format
- Supports multimodal input with text and images
- Supports tool extensions: web search, file search, function calling, remote MCP
```bash cURL theme={null}
curl https://api.apimart.ai/v1/responses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer " \
-d '{
"model": "gpt-5.2-pro",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "What is in this image?"
},
{
"type": "input_image",
"image_url": "https://openai-documentation.vercel.app/images/cat_and_otter.png"
}
]
}
]
}'
```
```python Python theme={null}
import requests
import os
url = "https://api.apimart.ai/v1/responses"
payload = {
"model": "gpt-5.2-pro",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "What is in this image?"
},
{
"type": "input_image",
"image_url": "https://openai-documentation.vercel.app/images/cat_and_otter.png"
}
]
}
]
}
headers = {
"Authorization": f"Bearer {os.environ.get('OPENAI_API_KEY')}",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/responses";
const payload = {
model: "gpt-5.2-pro",
input: [
{
role: "user",
content: [
{
type: "input_text",
text: "What is in this image?"
},
{
type: "input_image",
image_url: "https://openai-documentation.vercel.app/images/cat_and_otter.png"
}
]
}
]
};
const headers = {
"Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
url := "https://api.apimart.ai/v1/responses"
payload := map[string]interface{}{
"model": "gpt-5.2-pro",
"input": []map[string]interface{}{
{
"role": "user",
"content": []map[string]string{
{
"type": "input_text",
"text": "What is in this image?",
},
{
"type": "input_image",
"image_url": "https://openai-documentation.vercel.app/images/cat_and_otter.png",
},
},
},
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPENAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/responses";
String apiKey = System.getenv("OPENAI_API_KEY");
String payload = """
{
"model": "gpt-5.2-pro",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "What is in this image?"
},
{
"type": "input_image",
"image_url": "https://openai-documentation.vercel.app/images/cat_and_otter.png"
}
]
}
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"gpt-5.2-pro",
"input" => [
[
"role" => "user",
"content" => [
[
"type" => "input_text",
"text" => "What is in this image?"
],
[
"type" => "input_image",
"image_url" => "https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
]
]
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $apiKey,
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/responses")
api_key = ENV['OPENAI_API_KEY']
payload = {
model: "gpt-5.2-pro",
input: [
{
role: "user",
content: [
{
type: "input_text",
text: "What is in this image?"
},
{
type: "input_image",
image_url: "https://openai-documentation.vercel.app/images/cat_and_otter.png"
}
]
}
]
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer #{api_key}"
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/responses")!
let apiKey = ProcessInfo.processInfo.environment["OPENAI_API_KEY"] ?? ""
let payload: [String: Any] = [
"model": "gpt-5.2-pro",
"input": [
[
"role": "user",
"content": [
[
"type": "input_text",
"text": "What is in this image?"
],
[
"type": "input_image",
"image_url": "https://openai-documentation.vercel.app/images/cat_and_otter.png"
]
]
]
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/responses";
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
var payload = @"{
""model"": ""gpt-5.2-pro"",
""input"": [
{
""role"": ""user"",
""content"": [
{
""type"": ""input_text"",
""text"": ""What is in this image?""
},
{
""type"": ""input_image"",
""image_url"": ""https://openai-documentation.vercel.app/images/cat_and_otter.png""
}
]
}
]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
const char *api_key = getenv("OPENAI_API_KEY");
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/responses";
const char *payload = "{"
"\"model\":\"gpt-5.2-pro\","
"\"input\":[{\"role\":\"user\",\"content\":[{\"type\":\"input_text\",\"text\":\"What is in this image?\"},{\"type\":\"input_image\",\"image_url\":\"https://openai-documentation.vercel.app/images/cat_and_otter.png\"}]}]"
"}";
char auth_header[256];
snprintf(auth_header, sizeof(auth_header), "Authorization: Bearer %s", api_key);
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, auth_header);
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/responses"];
NSString *apiKey = [NSProcessInfo processInfo].environment[@"OPENAI_API_KEY"];
NSDictionary *payload = @{
@"model": @"gpt-5.2-pro",
@"input": @[
@{
@"role": @"user",
@"content": @[
@{
@"type": @"input_text",
@"text": @"What is in this image?"
},
@{
@"type": @"input_image",
@"image_url": @"https://openai-documentation.vercel.app/images/cat_and_otter.png"
}
]
}
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:[NSString stringWithFormat:@"Bearer %@", apiKey]
forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/responses"
let api_key = Sys.getenv "OPENAI_API_KEY"
let payload = {|{
"model": "gpt-5.2-pro",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "What is in this image?"
},
{
"type": "input_image",
"image_url": "https://openai-documentation.vercel.app/images/cat_and_otter.png"
}
]
}
]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" ("Bearer " ^ api_key)
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/responses');
final apiKey = Platform.environment['OPENAI_API_KEY'];
final payload = {
'model': 'gpt-5.2-pro',
'input': [
{
'role': 'user',
'content': [
{
'type': 'input_text',
'text': 'What is in this image?'
},
{
'type': 'input_image',
'image_url': 'https://openai-documentation.vercel.app/images/cat_and_otter.png'
}
]
}
]
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer $apiKey',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/responses"
api_key <- Sys.getenv("OPENAI_API_KEY")
payload <- list(
model = "gpt-5.2-pro",
input = list(
list(
role = "user",
content = list(
list(
type = "input_text",
text = "What is in this image?"
),
list(
type = "input_image",
image_url = "https://openai-documentation.vercel.app/images/cat_and_otter.png"
)
)
)
)
)
response <- POST(
url,
add_headers(
Authorization = paste("Bearer", api_key),
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": {
"id": "resp-9876543210",
"object": "response",
"created": 1677652288,
"model": "gpt-5.2-pro",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "This image shows a cat and an otter. They appear to be interacting with each other in a very cute and heartwarming scene. The cat and otter seem to be getting along well."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 156,
"completion_tokens": 45,
"total_tokens": 201
}
}
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, server temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
\##All APIs require Bearer Token authentication##
Get API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Model name
Supported models include:
* `gpt-5.2-pro`
* `gpt-5.2-codex`
* `qwen3.8-max`
* More models coming soon...
Input content list
Input array, each item contains `role` and `content` fields.
**💡 Quick fill (Try it area):**
1. Click "+ Add an item" to add an input item
2. `role` input: `user` (user message), `assistant` (AI response), or `system` (system prompt)
3. `content` add content blocks (can include text and images)
Role type
Options: `user` (user message), `assistant` (AI response, for multi-turn), `system` (system prompt, to set AI behavior)
Content array
Supports multiple types of content blocks, can include text and images.
Content type
Options:
* `input_text`: Text input
* `input_image`: Image input
Text content
Used when `type` is `input_text`, fill in the text content
Image URL
Used when `type` is `input_image`, fill in the image URL or base64 encoding
Supports two formats:
**1. Full image URL**
* Publicly accessible image URL (http\:// or https\://)
* Example: `https://example.com/image.jpg`
**2. Base64 encoded format**
* **Must use the complete Data URI format**
* Format: `data:image/{format};base64,{base64_data}`
* Supported image formats: jpeg, png, gif, webp
Controls output randomness, range 0-2
* Lower values (e.g. 0.2) make output more deterministic
* Higher values (e.g. 1.8) make output more random
Default: 1.0
Maximum number of tokens to generate
Different models have different maximum limits, please refer to specific model documentation
Whether to use streaming output
* `true`: Stream response (SSE format)
* `false`: Return complete response at once
Default: false
Nucleus sampling parameter, range 0-1
Controls diversity of generated text, recommended to use with temperature alternatively
Default: 1.0
Tools list for extending model capabilities
Supported tool types:
* **Web Search** (`web_search`): Real-time internet information search
* **File Search** (`file_search`): Search uploaded file content
* **Function Calling** (`function`): Call custom functions
* **Remote MCP** (`remote_mcp`): Connect to remote Model Context Protocol services
Example: `[{"type": "web_search"}]`
## Response
Unique identifier for the response
Object type, fixed as `response`
Creation timestamp
Actual model name used
List of generated replies
Choice index
Message content
Role type (assistant)
Generated text content
Finish reason
Possible values:
* `stop` - Natural completion
* `length` - Max length reached
* `content_filter` - Content filtering
Token usage statistics
Number of tokens in input
Number of tokens in output
Total number of tokens
## Usage Examples
### Text-Only Input
```json theme={null}
{
"model": "gpt-5.2-pro",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Hello, introduce artificial intelligence"
}
]
}
]
}
```
### Using Web Search Tool
```json theme={null}
{
"model": "gpt-5.2-pro",
"tools": [{"type": "web_search"}],
"input": "What positive news is there today?"
}
```
```bash cURL Example theme={null}
curl "https://api.apimart.ai/v1/responses" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer " \
-d '{
"model": "gpt-5.2-pro",
"tools": [{"type": "web_search"}],
"input": "What positive news is there today?"
}'
```
### Image Understanding
```json theme={null}
{
"model": "gpt-5.2-pro",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Describe this image"
},
{
"type": "input_image",
"image_url": "https://example.com/image.jpg"
}
]
}
]
}
```
### Multi-Image Analysis
```json theme={null}
{
"model": "gpt-5.2-pro",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Compare the similarities and differences of these two images"
},
{
"type": "input_image",
"image_url": "https://example.com/image1.jpg"
},
{
"type": "input_image",
"image_url": "https://example.com/image2.jpg"
}
]
}
]
}
```
### Base64 Encoded Image
```json theme={null}
{
"model": "gpt-5.2-pro",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Analyze this image"
},
{
"type": "input_image",
"image_url": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
}
]
}
]
}
```
### Using File Search Tool
```json theme={null}
{
"model": "gpt-5.2-pro",
"tools": [{"type": "file_search"}],
"input": "Based on uploaded documents, summarize the company's quarterly performance"
}
```
### Using Function Calling
```json theme={null}
{
"model": "gpt-5.2-pro",
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather information for a specified city",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, e.g.: Beijing"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["city"]
}
}
}
],
"input": "What's the weather like in Beijing today?"
}
```
### Using Remote MCP
```json theme={null}
{
"model": "gpt-5.2-pro",
"tools": [
{
"type": "remote_mcp",
"remote_mcp": {
"url": "https://mcp.example.com/api",
"auth_token": "your_mcp_token"
}
}
],
"input": "Query user information in the database"
}
```
### Combining Multiple Tools
```json theme={null}
{
"model": "gpt-5.2-pro",
"tools": [
{"type": "web_search"},
{"type": "file_search"},
{
"type": "function",
"function": {
"name": "calculate",
"description": "Perform mathematical calculations",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Mathematical expression"
}
},
"required": ["expression"]
}
}
}
],
"input": "Search for the latest Bitcoin price and calculate the total value of 100 Bitcoins"
}
```
## Content Type Specifications
### input\_text
Text input type
**Properties:**
* `type`: Fixed as `"input_text"`
* `text`: Text content (string)
### input\_image
Image input type
**Properties:**
* `type`: Fixed as `"input_image"`
* `image_url`: Image URL or Base64 encoded data URI
**Supported image formats:**
* JPEG
* PNG
* GIF
* WebP
**Image size limits:**
* Maximum file size: 20MB
* Recommended aspect\_ratio: No more than 2048x2048 pixels
## Tool Usage Details
### Web Search
The web search tool allows the model to access real-time internet information.
**Configuration example:**
```json theme={null}
{
"tools": [{"type": "web_search"}]
}
```
**Use cases:**
* Query latest news and current events
* Get real-time data (stocks, weather, exchange rates, etc.)
* Search for latest technical documentation
* Verify factual information
### File Search
The file search tool allows the model to search for relevant information in uploaded documents.
**Configuration example:**
```json theme={null}
{
"tools": [{"type": "file_search"}]
}
```
**Use cases:**
* Analyze internal corporate documents
* Search technical specifications and manuals
* Query contracts and legal documents
* Knowledge base Q\&A systems
### Function Calling
Define custom functions to enable the model to call external APIs or perform specific operations.
**Complete configuration example:**
```json theme={null}
{
"tools": [
{
"type": "function",
"function": {
"name": "get_stock_price",
"description": "Get real-time stock price",
"parameters": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Stock symbol, e.g.: AAPL"
},
"currency": {
"type": "string",
"enum": ["USD", "CNY"],
"description": "Currency unit",
"default": "USD"
}
},
"required": ["symbol"]
}
}
}
]
}
```
**Parameter descriptions:**
* `name`: Function name (required)
* `description`: Function description (required)
* `parameters`: Parameter definition using JSON Schema format
* `type`: Parameter type
* `properties`: Parameter property definitions
* `required`: List of required parameters
**Use cases:**
* Call third-party APIs
* Execute database queries
* Trigger business processes
* Integrate with internal systems
### Remote MCP
Connect to remote Model Context Protocol (MCP) services to extend model capabilities.
**Configuration example:**
```json theme={null}
{
"tools": [
{
"type": "remote_mcp",
"remote_mcp": {
"url": "https://your-mcp-server.com/api",
"auth_token": "your_auth_token",
"timeout": 30
}
}
]
}
```
**Parameter descriptions:**
* `url`: MCP server address (required)
* `auth_token`: Authentication token (optional)
* `timeout`: Timeout in seconds, default 30 seconds
**Use cases:**
* Connect to enterprise-level AI services
* Use domain-specific models
* Access protected data sources
* Distributed AI system integration
## Tool Response Format
When the model uses tools, the response format will include tool call information:
```json theme={null}
{
"id": "resp-123456",
"object": "response",
"created": 1677652288,
"model": "gpt-5.2-pro",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\": \"Beijing\"}"
}
}
]
},
"finish_reason": "tool_calls"
}
]
}
```
**Tool call workflow:**
1. Model receives user input
2. Analyzes whether tools are needed
3. If needed, returns tool call request
4. Client executes tool call
5. Returns tool results to model
6. Model generates final response
## Important Notes
1. **Image URL requirements**:
* Must be a publicly accessible URL
* Or use Base64 encoded Data URI format
2. **Token billing**:
* Images consume tokens based on their aspect\_ratio
* High-aspect\_ratio images are automatically resized to optimize costs
* Tool calls also consume additional tokens
3. **Content order**:
* Order of elements in content array affects model understanding
* Recommended to place text instructions first, then images
4. **Multimodal combinations**:
* Can mix multiple texts and images in one request
* Supports multi-turn conversations with context coherence
5. **Tool usage limitations**:
* When using multiple tools simultaneously, the model intelligently selects the most appropriate tool
* Function calling requires clear function definitions and parameter descriptions
* Web search results may be limited by region and time
6. **API compatibility**:
* Fully compatible with OpenAI Responses API format
* Seamlessly migrate existing OpenAI code
* Supports all OpenAI tool extension features
# qwen3.8-max Integration Guide
Source: https://docs.apimart.ai/en/api-reference/texts/qwen3.8-max/guide
POST https://api.apimart.ai/v1/chat/completions
- OpenAI-compatible: chat/completions and Responses
- Built-in tools only on Responses; thinking cannot be disabled
- Implicit/explicit context cache; PDF on chat endpoint only
- Billing = token fees + per-call tool fees
OpenAI SDK compatible: swap `base_url` and `api_key`. Model name is fixed **`qwen3.8-max`**.
```python theme={null}
from openai import OpenAI
client = OpenAI(
api_key="",
base_url="https://api.apimart.ai/v1",
)
resp = client.chat.completions.create(
model="qwen3.8-max",
messages=[{"role": "user", "content": "Describe Hangzhou in one sentence"}],
stream=False, # must set explicitly — see below
)
print(resp.choices[0].message.content)
```
Related APIs:
* [Chat Completions](/en/api-reference/texts/general/chat-completions)
* [OpenAI Responses](/en/api-reference/texts/openai/responses)
* [Model pricing API](/en/api-reference/texts/qwen3.8-max/pricing)
## Three easy pitfalls
### 1. `/v1/chat/completions` defaults to **streaming** if `stream` is omitted
```python theme={null}
# Omitting stream → SSE; parsing as non-stream fails
client.chat.completions.create(model="qwen3.8-max", messages=[...])
# Non-stream requires explicit False
client.chat.completions.create(
model="qwen3.8-max",
messages=[...],
stream=False,
)
```
This is **opposite** to OpenAI’s default (omit = non-stream). Easy to miss when porting SDK code.
### 2. Built-in tools work only on `/v1/responses`
`/v1/chat/completions` does **not** support built-in tools (they are ignored with **no error**). For web search, code interpreter, text-to-image search, or image-to-image search, use the [Responses API](/en/api-reference/texts/openai/responses).
### 3. Wrong tool names fail silently
Invalid tool names are accepted quietly. **`t2i_search` / `i2i_search` on pricing pages are not valid tool names**:
| Name you may see | Actual tool type |
| ------------------------- | ---------------------- |
| `t2i_search` (pricing UI) | **`web_search_image`** |
| `i2i_search` (pricing UI) | **`image_search`** |
## Built-in tools (Responses)
Declare in `/v1/responses` `tools` as `{"type": ""}`.
| Tool | Purpose | Constraints |
| ------------------ | ----------------------------------------------------------- | ------------------------------------------------------- |
| `web_search` | Search the web and cite | — |
| `web_extractor` | Fetch page body by URL | **Must be declared with `web_search`**; alone → **400** |
| `code_interpreter` | Run code in a sandbox | — |
| `web_search_image` | **Text→image search** (existing web images, not generation) | — |
| `image_search` | **Image→image search** | Provide an image in `input`; slower — prefer streaming |
### Web search
```python theme={null}
resp = client.responses.create(
model="qwen3.8-max",
input="One sentence about Shanghai weather tomorrow",
tools=[{"type": "web_search"}],
max_output_tokens=600,
)
```
### Web extract
```python theme={null}
resp = client.responses.create(
model="qwen3.8-max",
input="Fetch https://example.com and summarize the first screen",
tools=[
{"type": "web_search"},
{"type": "web_extractor"}, # missing web_search → 400
],
)
```
Typical error text:
```text theme={null}
The web_extractor tool must be executed with web_search tool.
```
### Image search
```python theme={null}
resp = client.responses.create(
model="qwen3.8-max",
input=[{
"role": "user",
"content": [
{"type": "input_image", "image_url": "https://example.com/your.jpg"},
{"type": "input_text", "text": "Find similar images"},
],
}],
tools=[{"type": "image_search"}],
stream=True, # recommended: this tool is noticeably slower
)
```
### Confirm a tool was called
Trust **`usage.x_tools`** (billing source of truth):
```json theme={null}
{
"output": [
{ "type": "reasoning" },
{ "type": "web_search_call" },
{
"type": "message",
"content": [{ "type": "output_text", "text": "..." }]
}
],
"usage": {
"input_tokens": 2528,
"output_tokens": 362,
"output_tokens_details": { "reasoning_tokens": 280 },
"x_tools": { "web_search": { "count": 1 } }
}
}
```
**Tools declared but not invoked are free** — they do not appear in `x_tools`.
## Thinking (reasoning)
**Thinking cannot be turned off.** Every request reasons before answering:
* Thinking tokens bill as **output**, via `output_tokens_details.reasoning_tokens`
* Responses: `reasoning` items in `output`; chat stream: `delta.reasoning_content`
* `enable_thinking: false` is ignored in stream mode; non-stream is degraded — **not recommended**
Output token usage with thinking is often much higher. Cap cost with `max_output_tokens`.
## Context cache
Reuse long prompts to cut input cost.
### Implicit cache (automatic)
Repeated requests with the same prefix may hit cache from the second call; hits bill at cache rates (\~1/8 of normal input). Hit size is block-rounded; **full hit is not guaranteed**.
### Explicit cache
Mark content with `cache_control`:
```python theme={null}
client.chat.completions.create(
model="qwen3.8-max",
messages=[
{
"role": "system",
"content": [
{
"type": "text",
"text": "",
"cache_control": {"type": "ephemeral"},
}
],
},
{"role": "user", "content": "Answer based on the context above"},
],
stream=False,
)
```
| Item | Notes |
| ----------------- | ----------------------------------------- |
| Min cache content | **≥ 1024 tokens** |
| TTL | **5 minutes** |
| Cache create | Slightly more expensive than normal input |
| Explicit hit | Usually cheaper than implicit hit |
Response distinction:
```json theme={null}
// create
"prompt_tokens_details": {
"cache_creation_input_tokens": 1482,
"cache_type": "ephemeral",
"cached_tokens": 0
}
// hit
"prompt_tokens_details": {
"cache_creation_input_tokens": 0,
"cache_type": "ephemeral",
"cached_tokens": 1482
}
```
Implicit hits typically only set `cached_tokens` (may omit `cache_type: "ephemeral"`).
## PDF understanding
Supported **only** on `/v1/chat/completions`. Responses **silently ignores** PDFs (no error).
```python theme={null}
client.chat.completions.create(
model="qwen3.8-max",
messages=[{
"role": "user",
"content": [
{
"type": "file",
"file": {"file_url": "https://example.com/doc.pdf"},
},
# or base64:
# {"type": "file", "file": {"file_data": "data:application/pdf;base64,...", "filename": "doc.pdf"}}
{"type": "text", "text": "What is this document about?"},
],
}],
stream=False,
)
```
* PDFs are understood as images and bill as **image input tokens** (\~letter \~2082 tok/page, A4 \~2147 tok/page order of magnitude); **no extra parse fee**
* `fileid://` is **invalid** here (other-model mechanism) and treated as plain text
## Billing model
Total = **token fees** + **per-call tool fees** (independent).
| Item | How billed |
| -------------- | ------------------------------------------------------------- |
| Input | Per token; cache hits use cache rates |
| Output | Per token; **thinking counts as output** |
| Built-in tools | Actual calls in `usage.x_tools` (often priced per 1000 calls) |
Fetch unit prices via the [pricing API](/en/api-reference/texts/qwen3.8-max/pricing):
```http theme={null}
GET /api/pricing/model?model=qwen3.8-max
```
Read `data.pricing.effective_rates` (includes group discount) and `data.pricing.extras.tools`.
## Limits
| Item | Value |
| ------------------ | ---------------------------------------- |
| Max input | 983,616 tokens (\~1M) |
| Max output | 131,072 tokens |
| Cache read / write | Supported / supported |
| Multimodal input | Images, video, etc. (e.g. `input_image`) |
## FAQ
**Q: I passed `tools` but nothing ran?**\
① Use `/v1/responses`; ② correct tool names (not `t2i_search`); ③ check `usage.x_tools` — missing means not invoked and not billed.
**Q: `web_extractor` returns 400?**\
Declare it together with `web_search`.
**Q: Non-stream is slow?**\
Tool calls (especially `image_search`) take longer. Prefer streaming when timeouts matter.
**Q: Can I disable thinking to save money?**\
No. Cap with `max_output_tokens`, or switch to a model that allows disabling thinking.
**Q: How do I check usage?**
```http theme={null}
GET /v1/dashboard/billing/usage
GET /v1/dashboard/billing/subscription
```
# Model Pricing API
Source: https://docs.apimart.ai/en/api-reference/texts/qwen3.8-max/pricing
GET https://api.apimart.ai/api/pricing/model?model=qwen3.8-max
- GET /api/pricing/model for display rates
- Read only data.pricing; effective_rates is what users pay
- Tool prices must be multiplied by price_factor
- Contract is generic for TokenPricingV2 models
Examples use `qwen3.8-max`, but the `data.pricing` shape is **shared** by all **TokenPricingV2** models.
```http theme={null}
GET /api/pricing/model?model=qwen3.8-max
```
Model behavior and billing rules: [qwen3.8-max guide](/en/api-reference/texts/qwen3.8-max/guide).
This endpoint **does not require authentication**. Do not send `Authorization`.
## Request parameters
Model ID, e.g. `qwen3.8-max`. **Required**; omitting it returns `400 Missing model parameter`.
## Read only `data.pricing`
The response may include several overlapping price blocks — **frontends should only use `data.pricing`**:
| Block | Purpose | Frontend |
| -------------------- | ---------------------------------- | ------------------------------------ |
| `data.pricing` | Flat, self-describing display view | ✅ **Use this** |
| `data.token_price` | Legacy flat copy | ❌ Compatibility only; missing fields |
| `data.token_pricing` | Internal snapshot | ❌ Implementation details |
`token_price` may **omit** fields like `explicit_cached_input`, so estimates run high. New billing dimensions are added only under `pricing`.
```json theme={null}
{
"token_price": {
"input": 1.714286,
"cached_input": 0.214286,
"cache_write": 2.142857,
"output": 5.142857
},
"pricing": {
"rates": {
"input": 1.714286,
"cached_input": 0.214286,
"cache_write": 2.142857,
"explicit_cached_input": 0.142857,
"output": 5.142857
}
}
}
```
## `rates` vs `effective_rates`
| Field | Meaning |
| ----------------- | -------------------------------------------------- |
| `rates` | List / strikethrough price |
| `effective_rates` | **What to display as payable** (discounts applied) |
| `discount_rate` | Model discount (`1` = none) |
| `group_ratio` | Group multiplier |
| `price_factor` | `discount_rate × group_ratio` |
```json theme={null}
{
"discount_rate": 1,
"group_ratio": 0.8,
"price_factor": 0.8,
"rates": { "input": 1.714286, "output": 5.142857 },
"effective_rates": { "input": 1.3714288, "output": 4.1142856 }
}
```
**Use `effective_rates` for UI prices — do not multiply yourself.** Use `rates` only when showing list price alongside.
`group` is often `default`: public pricing pages quote default. A user’s real charge uses their group and **may be lower** than the displayed price.
`rates` / `effective_rates` use **`usd_per_million_tokens`** (USD per 1M tokens).
## Tool prices: `extras.tools` is list price only
Asymmetry in the current API:
| | List | Payable |
| ------------------ | ----------------------- | ------------------------------------------------------------ |
| Tokens | `rates` | `effective_rates` (precomputed) |
| **Built-in tools** | `extras.tools[x].price` | **No effective field — multiply by `price_factor` yourself** |
```js theme={null}
const listed = pricing.extras.tools.web_search.price;
const actual = listed * pricing.price_factor; // display this
```
Respect `unit` — **do not hardcode “per 1k calls”**:
| `unit` | Meaning | Cost |
| ---------------------- | -------------- | ------------------------------------------- |
| `usd_per_1000_queries` | Per 1000 calls | `price / 1000 × count` |
| `usd_per_page` | Per page | `price × pages` (**do not** divide by 1000) |
## Three-state field semantics
| Case | JSON | Meaning |
| --------------- | ----------------------------------- | ------------------------------------------------- |
| Present | `"explicit_cached_input": 0.142857` | Bill at this rate |
| **Key missing** | — | Dimension **not applicable** (not zero, not free) |
| Explicit `0` | `"price": 0` | **Actually free** — show as free |
Examples:
* **Missing `output_thinking`** → single output rate; do **not** render “thinking is free”. For `qwen3.8-max`, thinking cannot be disabled and there is one output price.
* **Missing `extras.google_web_search`** → Vertex-only; Bailian-style search is under `extras.tools.web_search`.
* Tool with `price: 0` → **explicit free** (e.g. promo); show free.
## Multi-tier: only `tier_count`
```json theme={null}
{
"billing_type": "tiered_token",
"tier_count": 1
}
```
| Check | Behavior |
| ------------------ | ------------------------------------------------------------------------------------------------------------ |
| `tier_count === 1` | **Do not** render a tier table; use `rates` / `effective_rates` |
| `tier_count > 1` | `tiers[]` present; `up_to_input_tokens` is inclusive upper bound; missing key = uncapped (usually last tier) |
Tier rule: pick one tier from **total input tokens of the request**, then price the **whole request** at that tier (not progressive). Values in `tiers` are list prices — multiply by `price_factor`.
Do **not** use `billing_type === "tiered_token"` to detect multi-tier pricing — single-tier models can still use that value. **Only trust `tier_count`.**
## `limits` (not prices)
```json theme={null}
{
"limits": {
"max_input_tokens": 983616,
"max_output_tokens": 131072,
"supports_cache_read": true,
"supports_cache_write": true
}
}
```
* `supports_cache_*`: capability flags; if `false`, do not present cache rates as available even if present in `rates`.
* `max_output_tokens`: pre-charge style cap when `max_tokens` is omitted — not a price.
## TypeScript types
```ts theme={null}
type ToolItem = {
unit: "usd_per_1000_queries" | "usd_per_page";
price: number; // list price; × price_factor for display
precharge_queries?: number;
};
type Rates = {
input?: number;
cached_input?: number;
explicit_cached_input?: number;
cache_write?: number;
cache_write_5m?: number;
cache_write_1h?: number;
output?: number;
output_thinking?: number;
text_input?: number;
cached_text_input?: number;
image_input?: number;
cached_image_input?: number;
text_output?: number;
image_output?: number;
};
type ModelPricing = {
billing_type: string;
source: "v1" | "v2";
unit: "usd_per_million_tokens";
pricing_mode: "standard" | "image_modalities";
discount_rate: number;
group: string;
group_ratio: number;
price_factor: number;
resolved_from?: string;
rates?: Rates;
effective_rates?: Rates;
tier_count: number;
tiers?: (Rates & { up_to_input_tokens?: number })[];
limits?: {
max_input_tokens?: number;
max_output_tokens?: number;
supports_cache_read: boolean;
supports_cache_write: boolean;
};
extras?: {
tools?: Record;
google_web_search?: ToolItem;
};
};
```
### Tool row helper
```js theme={null}
const toolRows = Object.entries(pricing.extras?.tools ?? {}).map(
([tool, item]) => ({
tool,
actual: item.price * pricing.price_factor,
suffix: item.unit === "usd_per_page" ? "/ page" : "/ 1k calls",
free: item.price === 0,
}),
);
```
## Common mistakes
| Wrong | Right |
| -------------------------------- | ------------------------------------------------ |
| Read `token_price` | Read `pricing.rates` / `pricing.effective_rates` |
| Multiply `rates` yourself | Use `effective_rates` |
| Show raw `extras.tools[x].price` | Multiply by **`price_factor`** |
| Hardcode “per 1k calls” | Branch on `item.unit` |
| Treat missing keys as 0 / free | Missing = **N/A**; only explicit `0` is free |
| Use `billing_type` for tiers | Use `tier_count > 1` |
| Read `tiers` for single-tier | Use `rates` |
| Mix `pricing_mode` fields | `standard` vs `image_modalities` are exclusive |
## Request examples
```bash theme={null}
curl --request GET \
--url 'https://api.apimart.ai/api/pricing/model?model=qwen3.8-max' \
--header 'Accept: application/json'
```
```python theme={null}
import requests
url = "https://api.apimart.ai/api/pricing/model"
params = {"model": "qwen3.8-max"}
headers = {"Accept": "application/json"}
print(requests.get(url, params=params, headers=headers).json())
```
# seedance-1-0-pro Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/doubao/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns task ID for subsequent queries
- Supports text-to-video, image-to-video (first frame/last frame)
- Supports landscape, portrait, and square aspect ratios
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "seedance-1-0-pro-fast",
"prompt": "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "1080p"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "seedance-1-0-pro-fast",
"prompt": "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "1080p"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "seedance-1-0-pro-fast",
prompt: "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
duration: 5,
aspect_ratio: "16:9",
resolution: "720p"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "seedance-1-0-pro-fast",
"prompt": "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "seedance-1-0-pro-fast",
"prompt": "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "1080p"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"seedance-1-0-pro-fast",
"prompt" => "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration" => 5,
"aspect_ratio" => "16:9",
"resolution" => "720p"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "seedance-1-0-pro-fast",
prompt: "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
duration: 5,
aspect_ratio: "16:9",
resolution: "720p"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "seedance-1-0-pro-fast",
"prompt": "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "1080p"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""seedance-1-0-pro-fast"",
""prompt"": ""A cute kitten playing in the sunlight, fluffy fur, bright eyes"",
""duration"": 5,
""aspect_ratio"": ""16:9"",
""resolution"": ""720p""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `seedance-1-0-pro-fast` - Fast version, quick generation, suitable for preview and iteration
* `seedance-1-0-pro-quality` - High-quality version, longer generation time, better quality
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description
Describe scenes, actions, styles in detail for better generation results
Example: `"Sunset at the beach, golden sunlight on the sea, waves gently hitting the sand"`
Video duration (seconds)
Supported range: `2` \~ `12` seconds
Default: `5`
Video aspect ratio
Options:
* `16:9` - Landscape
* `9:16` - Portrait
* `1:1` - Square
* `4:3` - Traditional ratio
* `3:4` - Vertical traditional ratio
* `21:9` - Ultra-wide
Default: `16:9`
Video resolution
Options:
* `480p` - Standard definition
* `720p` - High definition
* `1080p` - Full HD
Default: `1080p`
Seed integer for controlling the randomness of generated content
Value range: Integer between `-1` and `2^32-1`
* With the same request, if the model receives different seed values (e.g., not specifying seed or setting seed to -1, which will use a random number), different results will be generated
* With the same request, if the model receives the same seed value, similar results will be generated, but not guaranteed to be identical
## Resolution and Aspect Ratio Combinations
| Resolution | Supported Aspect Ratios | Notes |
| ---------- | ------------------------------- | ------------- |
| 480p | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | All supported |
| 720p | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | All supported |
| 1080p | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | All supported |
Image array with roles for more precise control
Image URL address
Image role
Options:
* `first_frame` - First frame image, as video starting frame (only one supported)
* `last_frame` - Last frame image, as video ending frame (quality version only, only one supported)
Example:
```json theme={null}
[
{"url": "https://example.com/start.png", "role": "first_frame"},
{"url": "https://example.com/end.png", "role": "last_frame"}
]
```
* Only one image per role is supported
* `last_frame` is only supported by `seedance-1-0-pro-quality` version, fast version does not support first and last frame together
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Quick Preview Landscape Video
```json theme={null}
{
"model": "seedance-1-0-pro-fast",
"prompt": "Sunset at the beach, golden sunlight on the sea, waves gently hitting the sand"
}
```
### Case 2: High-Quality Portrait Short Video
```json theme={null}
{
"model": "seedance-1-0-pro-quality",
"prompt": "A girl spinning under cherry blossom trees, petals falling with the wind",
"duration": 5,
"aspect_ratio": "9:16",
"resolution": "1080p"
}
```
### Case 3: Dynamic Transition Effect (First/Last Frame)
```json theme={null}
{
"model": "seedance-1-0-pro-quality",
"prompt": "Scene transitions from day to night, city lights gradually turning on",
"image_with_roles": [
{"url": "https://example.com/day.png", "role": "first_frame"},
{"url": "https://example.com/night.png", "role": "last_frame"}
],
"duration": 5
}
```
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# FLUX 3 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/flux-3-video/generation
POST https://api.apimart.ai/v1/videos/generations
- Asynchronous processing mode, returns a task ID for subsequent queries
- Unified entry: text-to-video / image-to-video / video continuation / draft two-step
- Output H.264 + AAC with synced audio, duration 5~20 seconds
- Resolution hd / fhd, seven aspect ratios
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9",
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "flux-3-video",
prompt: "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
duration: 5,
resolution: "hd",
aspect_ratio: "16:9",
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Parameter conflict or invalid value",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
## Authorization
All endpoints require Bearer Token authentication
Get your API Key from the [API Key Management Page](https://apimart.ai/keys):
```
Authorization: Bearer YOUR_API_KEY
```
## Generation Modes
`flux-3-video` is a **unified entry**: mode is inferred from fields, or set explicitly with `mode`.
| Mode | Trigger | Notes |
| ---------------------------- | ------------------------------------ | --------------------------------------------------------------------- |
| **Text-to-video (t2v)** | `prompt` only | Pure text |
| **Image-to-video (i2v)** | `image_urls` | Keyframes; see below |
| **Video continuation (v2v)** | `video_url` / `video_urls` | Higher unit price; if both image and video are set, continuation wins |
| **Draft → final** | `draft:true` or `draft_from_task_id` | Cheap preview, then full-price final |
`mode` values: `t2v` / `i2v` / `v2v` / `draft_enhance`, or official spellings `text-to-video` / `image-continuation` / `video-continuation`. **Explicit `mode` has highest priority.**
### Image-to-video keyframe semantics
Order in `image_urls` is semantic — do not sort or dedupe:
| Count | Meaning |
| ----- | ---------------------------------------------------------------------------------- |
| 1 | **Start frame** |
| 2 | First start, second **end frame** |
| 3\~10 | First start, last end, middle frames **evenly spaced** (set `duration` explicitly) |
## Request Parameters
Fixed value: `flux-3-video`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Prompt. **Must not be sent** when using `draft_from_task_id` (rejected if present).
Duration in seconds, integer **5\~20**, default `5`
**`duration: "auto"` is not supported** (billing needs a fixed second count). Omit, `"auto"`, or non-integers → treated as **5 seconds** without error and without adaptive length.
For **video continuation**, the delivered duration may be shorter than requested (e.g. request 5s, get 4s). The request is pre-charged for the requested seconds and the difference is refunded after completion; final amount is query `cost`. Text/image-to-video do not show this gap.
Resolution
* `hd` (default; also accepts `720p`)
* `fhd` (also accepts `1080p`)
Measured: `hd` \~1280×704 at 16:9; `fhd` \~1920×1088.
Draft mode (`draft:true`) **only** allows `hd`.
Aspect ratio
Options: `21:9`, `2:1`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`, or `auto` (default; chosen automatically from the prompt and assets)
Image-to-video keyframes, **1\~10**, public http(s) URL or base64
Input video for continuation (mp4, public URL or base64)
Same as `video_url`; uses the **first** item (compat)
Generate synced audio, default `true`. `false` yields silent video (**no discount**)
Draft mode: \~**1/3 price** low-quality preview; only with `resolution: hd`
Draft → final: ID of **your** successful draft task
* Only `resolution` may change; prompt, duration, images, video cannot
* Charged at full final price; draft fee is not credited
* Mutually exclusive with `draft:true`
Moderation tolerance **0\~4**, default `2` (higher = more permissive)
Do not confuse with FLUX.2 images (0~~5) or Kontext (0~~6).
Explicit mode (optional); see Generation Modes
## Draft Mode
Two-step workflow when iterating is expensive:
```
Step 1 draft:true → ~1/3 price low-quality preview
Step 2 draft_from_task_id → full-price final matching the draft look
```
### Create draft
```json theme={null}
{
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table",
"duration": 5,
"draft": true
}
```
### Draft to final
```json theme={null}
{
"model": "flux-3-video",
"draft_from_task_id": "task_01K_DRAFT...",
"resolution": "fhd"
}
```
Draft-to-final re-renders at full quality using the draft’s saved params (mode / prompt / seed / assets). Continuation drafts finalize at continuation final rates.
## Request Examples
### Text-to-video (portrait)
```json theme={null}
{
"model": "flux-3-video",
"prompt": "Rainy Tokyo street at night, neon in puddles, a person walks with an umbrella.",
"duration": 8,
"resolution": "fhd",
"aspect_ratio": "9:16"
}
```
### Image-to-video (start + end frame)
```json theme={null}
{
"model": "flux-3-video",
"prompt": "Slow push-in as a flower opens from bud to bloom",
"image_urls": [
"https://example.com/bud.jpg",
"https://example.com/bloom.jpg"
],
"duration": 5
}
```
### Video continuation
```json theme={null}
{
"model": "flux-3-video",
"prompt": "Camera keeps following as the lead turns toward a distant lighthouse",
"video_url": "https://example.com/clip.mp4",
"duration": 5
}
```
### Silent video
```json theme={null}
{
"model": "flux-3-video",
"prompt": "...",
"audio": false
}
```
## Constraints
| Limit | Value |
| ------------------ | ---------------------------------------------------- |
| Duration | Integer 5\~20 (`auto` unsupported; `21` is rejected) |
| Keyframes | 1\~10 |
| Resolution | `hd` / `fhd` only; draft only `hd` |
| Aspect ratio | Seven options or `auto` |
| `safety_tolerance` | 0\~4 |
### Common submit errors (usually not charged)
| Case | Notes |
| ----------------------------------------------------- | ----------------------------- |
| Missing `prompt` | Required except draft enhance |
| Invalid `resolution` / `aspect_ratio` / `duration` | Out of range |
| Keyframes > 10 | Cap exceeded |
| Explicit `i2v` without images / `v2v` without video | Mode/asset mismatch |
| `draft:true` + `fhd` | Draft is hd only |
| Invalid / non-draft / unfinished `draft_from_task_id` | Finalization preconditions |
| Changing prompt / duration on finalize | Only `resolution` allowed |
| Both `draft` and `draft_from_task_id` | Mutually exclusive |
Moderation failures end as `failed` with **full refund**.
## Capability Coverage
| Capability | Status |
| ---------------------------------- | ------------------------------------------------ |
| t2v / i2v / v2v | ✅ Auto or explicit `mode` |
| Draft / draft enhance | ✅ `draft` / `draft_from_task_id` |
| Synced audio | ✅ On by default; `audio:false` off (no discount) |
| Timed keyframes `[seconds, image]` | ❌ Evenly spaced keyframe array only |
| `duration: "auto"` | ❌ Not supported |
## Response
Status code; 200 on success
Response data array
Task status; `submitted` on create
Task ID for polling
**Query results**
Video generation is async. Poll [Get Task Status](/en/api-reference/tasks/status).
Recommended interval **5\~10 seconds**; client timeout **15 minutes** (20s fhd is slower). Measured \~60s for `t2v` + `hd` + 5s.
On success use `result.videos[0].url`; assets are mirrored to the platform CDN. `cost` is the final charge. Failures are fully refunded.
# Gemini Omni 1.1 Flash Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/gemini-omni-1.1-flash/generation
POST https://api.apimart.ai/v1/videos/generations
- Google's official Gemini Omni 1.1 Flash all-in-one multimodal video generation model
- Supports text-to-video, image-to-video, multi-subject references, first-and-last-frame interpolation, video editing, and extension
- Supports 360p / 720p / 1080p / 4K, 24fps, 3–10 second output with generated audio
- Asynchronous task API; query the generated result by task ID after submission
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gemini-omni-1.1-flash",
"prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
"aspect_ratio": "16:9",
"resolution": "1080p"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "gemini-omni-1.1-flash",
"prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
"aspect_ratio": "16:9",
"resolution": "1080p"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "gemini-omni-1.1-flash",
prompt: "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
aspect_ratio: "16:9",
resolution: "1080p"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "gemini-omni-1.1-flash",
"prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
"aspect_ratio": "16:9",
"resolution": "1080p",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KS1H7ZYSJWH1N779S2FSHTKA"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Check your API key.",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance. Top up and try again.",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests. Try again later.",
"type": "rate_limit_error"
}
}
```
## Authentication
All endpoints require authentication with a Bearer token.
Get an API key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API key.
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request parameters
Video generation model name. Must be `gemini-omni-1.1-flash`.
Text instructions. For text-to-video, describe the scene. For image-to-video, video editing, or extension, describe the motion, style, or requested edit.
Provide at least one of `prompt` or media (`image_urls`, first/last frame images, or `video_urls`).
Output video resolution. Values are case-insensitive.
Available values:
* `360p`
* `720p` (default)
* `1080p`
* `4k`
`2160p` is treated as `4k`. The resolution determines the task's deposit tier and primary video output cost.
An unsupported resolution returns an `invalid_resolution` error.
Video aspect ratio, used to select landscape or portrait output.
Supported:
* `16:9` - Landscape (default)
* `9:16` - Portrait
Other values are treated as `16:9`.
When `video_urls` is provided, the output usually follows the input video's aspect ratio, so `aspect_ratio` may not take effect.
Reference image array. Only publicly accessible HTTP/HTTPS URLs are supported.
* Provide 1 image: used as the video's starting frame by default
* Provide multiple images: used as multi-subject or style references; describe each image's purpose and relationships in `prompt`
`image_urls` and first/last frame images can contain at most 10 images in total.
First-frame image. Only publicly accessible HTTP/HTTPS URLs are supported.
* Provided alone: uses the image as the video's starting frame
* Provided with `last_frame_image`: generates a video that transitions smoothly from the first frame to the last frame
Last-frame image. Only publicly accessible HTTP/HTTPS URLs are supported, and it must be provided with `first_frame_image`.
Providing only `last_frame_image` returns an `invalid_frame_images` error. Use the same aspect ratio for both frame images and match it to `aspect_ratio`.
For first-frame or first-and-last-frame generation, the following methods have the same effect. **Choose one; do not provide both**:
* Use `first_frame_image` / `last_frame_image`
* Use `image_with_roles` with `role` set to `first_frame` / `last_frame`
Image array with roles. It is an equivalent alternative to `first_frame_image` / `last_frame_image` and can also declare reference images.
A publicly accessible image HTTP/HTTPS URL.
Image role:
* `first_frame`: First frame
* `last_frame`: Last frame; a first frame must also be present
* `reference`: Reference image; other roles that are not first or last frame are also treated as references
Example:
```json theme={null}
[
{"url": "https://example.com/start.jpg", "role": "first_frame"},
{"url": "https://example.com/end.jpg", "role": "last_frame"}
]
```
If `image_urls` is also provided, it takes precedence for reference images and is not combined with references in `image_with_roles`. All effective images, including first and last frames, are limited to 10 in total.
Array of videos to edit or extend. Currently, at most one video can be provided, and it must be no longer than 10 seconds.
Only publicly accessible direct HTTP/HTTPS video URLs are supported. YouTube links are not supported.
`video_urls` and `extend_from_task_id` are mutually exclusive. Provide only one.
Additional parameters used to explicitly specify the generation intent.
Available task types:
* `text_to_video`: Text-to-video
* `image_to_video`: Image-to-video
* `reference_to_video`: Reference-to-video
* `edit`: Video editing
* `extend`: Video extension
If omitted, the system infers the task from the inputs and prompt.
For first-and-last-frame interpolation, the model infers the task automatically and the platform does not pass `metadata.task`.
The local `task_id` of the previous generation task. Use it for conversational editing or further extension without re-uploading the previous video.
The referenced task must belong to the current user, have succeeded, and be a Gemini Omni model task.
`extend_from_task_id` and `video_urls` are mutually exclusive. Provide only one.
This model has no `duration` parameter. The model determines each output's duration from the content, typically 3–10 seconds. To control pacing, describe it in `prompt` using natural language or time ranges.
## Response
Response status code. `200` indicates success.
Returned task array.
Initial task status. A successful submission returns `submitted`.
Unique task identifier used to query task status and results.
## Query task result
Video generation is asynchronous. After submission returns a `task_id`, use [Get task status](/en/api-reference/tasks/status) to query progress and results.
```bash cURL theme={null}
curl --request GET \
--url https://api.apimart.ai/v1/tasks/task_01KS1H7ZYSJWH1N779S2FSHTKA \
--header 'Authorization: Bearer '
```
Poll every 5–10 seconds and stop when the status becomes `completed` or `failed`. Set the overall client timeout to 10 minutes.
### Successful result example
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KS1H7ZYSJWH1N779S2FSHTKA",
"status": "completed",
"progress": 100,
"cost": 1.52,
"credits_cost": 15.2,
"result": {
"videos": [
{
"url": ["https://cdn.example.com/gemini_omni_xxx.mp4"],
"expires_at": 1788518400
}
]
}
}
}
```
## Use cases
### Use case 1: Text-to-video (4K)
```json theme={null}
{
"model": "gemini-omni-1.1-flash",
"prompt": "a blue butterfly landing on a flower, macro, soft light, no dialogue",
"aspect_ratio": "9:16",
"resolution": "4k"
}
```
### Use case 2: First-and-last-frame interpolation
```json theme={null}
{
"model": "gemini-omni-1.1-flash",
"prompt": "smooth transition, camera slowly pushes in",
"first_frame_image": "https://example.com/start.jpg",
"last_frame_image": "https://example.com/end.jpg",
"resolution": "720p"
}
```
### Use case 3: Multi-subject references
```json theme={null}
{
"model": "gemini-omni-1.1-flash",
"prompt": "the cat playfully bats at the ball of yarn",
"image_urls": [
"https://example.com/cat.png",
"https://example.com/yarn.png"
],
"resolution": "720p"
}
```
### Use case 4: Declare first and last frames with image roles
```json theme={null}
{
"model": "gemini-omni-1.1-flash",
"prompt": "a smooth cinematic transition from sunrise to a starry night",
"image_with_roles": [
{"url": "https://example.com/sunrise.jpg", "role": "first_frame"},
{"url": "https://example.com/night.jpg", "role": "last_frame"}
],
"resolution": "1080p"
}
```
### Use case 5: Video editing
```json theme={null}
{
"model": "gemini-omni-1.1-flash",
"prompt": "Make the violin invisible. Keep everything else the same.",
"video_urls": ["https://example.com/clip.mp4"]
}
```
Use short, specific prompts for video editing. To change only one part, add `Keep everything else the same` to preserve consistency elsewhere.
### Use case 6: Conversational extension
```json theme={null}
{
"model": "gemini-omni-1.1-flash",
"prompt": "Extend this video: the camera pans across the mountains.",
"extend_from_task_id": "task_01AAA"
}
```
# Gemini Omni Flash Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/gemini-omni-flash-preview/generation
POST https://api.apimart.ai/v1/videos/generations
- Google's official Gemini Omni Flash all-in-one multimodal video generation model
- Supports Text-to-Video, Image-to-Video, and Video-to-Video (editing), with mixed text + image + video input
- Outputs 720p / 24fps, 3-10 seconds, with audio; supports conversational multi-turn editing
- Asynchronous task API. Submit a task first, then query the result by task ID
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gemini-omni-flash-preview",
"prompt": "a red apple on a wooden table, short cinematic clip",
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "gemini-omni-flash-preview",
"prompt": "a red apple on a wooden table, short cinematic clip",
"aspect_ratio": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "gemini-omni-flash-preview",
prompt: "a red apple on a wooden table, short cinematic clip",
aspect_ratio: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "gemini-omni-flash-preview",
"prompt": "a red apple on a wooden table, short cinematic clip",
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KS1H7ZYSJWH1N779S2FSHTKA"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance. Please recharge and try again",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests. Please try again later",
"type": "rate_limit_error"
}
}
```
## Authentication
All requests require Bearer Token authentication.
Get an API key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API key.
Add the following header when making requests:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name. Must be `gemini-omni-flash-preview`.
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text instruction. For Text-to-Video, it is a scene description; for Image/Video-to-Video, it is an action / style / editing instruction.
`prompt` and reference materials (`image_urls` / `video_urls`) — **provide at least one of them**.
Reference images, up to **16**. Each item is an `http(s)://` URL.
Supports JPEG / PNG. For multiple subjects (e.g. "cat + ball of yarn"), you can pass multiple images and describe how they interact in the `prompt`.
Reference / video to be edited, **at most 1** (multiple video references are not supported). Can be an `http(s)://` direct link or `data:video/...`.
* Reference videos are 1-24 seconds; the official recommendation is **≤3 seconds**.
* `video_urls` and `extend_from_task_id` are **mutually exclusive**; provide only one of them, not both at the same time.
Video aspect ratio, which actually controls the output frame orientation.
When `video_urls` is provided, the `aspect_ratio` parameter has no effect.
Supported values only:
* `16:9` - landscape (default)
* `9:16` - portrait
Other values are treated as `16:9`.
Video resolution. Currently only `720p` is supported.
Previous task ID: fill in the \*\* `task_id`\*\* of the previous generation task.
`extend_from_task_id` and `video_urls` are **mutually exclusive**; provide only one of them, not both at the same time.
## Response
Response status code. Successful requests return `200`.
Returned task array.
Initial task status. It is `submitted` after successful submission.
Unique task ID for querying task status and result.
## Query Task Result
Video generation is asynchronous. After submission, the API returns a `task_id`. Use the [Get task status](/en/api-reference/tasks/status) endpoint to query progress and results.
### Successful Result Example
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KS1H7ZYSJWH1N779S2FSHTKA",
"status": "completed",
"progress": 100,
"created": 1779246294,
"completed": 1779246334,
"actual_time": 40,
"estimated_time": 60,
"cost": 1.0,
"credits_cost": 10,
"result": {
"videos": [
{
"url": ["https://cdn.example.com/gemini_omni_xxx.mp4"],
"expires_at": 1779332760
}
]
}
}
}
```
## Use Cases
### Scenario 1: Text-to-Video
```json theme={null}
{
"model": "gemini-omni-flash-preview",
"prompt": "a blue butterfly landing on a flower, macro, soft light",
"aspect_ratio": "9:16"
}
```
### Scenario 2: Image-to-Video
```json theme={null}
{
"model": "gemini-omni-flash-preview",
"prompt": "turn this drawing into realistic footage, use it only as a motion guide",
"image_urls": ["https://example.com/sketch.jpg"]
}
```
### Scenario 3: Video-to-Video
```json theme={null}
{
"model": "gemini-omni-flash-preview",
"prompt": "when the person touches the mirror, make it ripple like liquid",
"video_urls": ["https://example.com/clip.mp4"]
}
```
# Grok Imagine 1.5 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/grok-imagine/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns task ID for subsequent queries
- High-quality AI video generation, supports text-to-video and image-to-video
- Flexible aspect ratio and quality options for different creative needs
**Model name**: Use `grok-imagine-1.5-video-ext` for this endpoint.
```bash cURL theme={null}
# Set model to "grok-imagine-1.5-video-ext"
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "grok-imagine-1.5-video-ext",
"prompt": "A dog running on the beach, sunny weather, slow motion",
"size": "16:9",
"duration": 6,
"resolution": "720p"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "grok-imagine-1.5-video-ext",
"prompt": "A dog running on the beach, sunny weather, slow motion",
"size": "16:9",
"duration": 6,
"resolution": "720p"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "grok-imagine-1.5-video-ext",
prompt: "A dog running on the beach, sunny weather, slow motion",
size: "16:9",
duration: 6,
resolution: "720p"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"task_id": "task_01JNXXXXXXXXXXXXXXXXXX",
"status": "submitted"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway, server temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All APIs require Bearer Token authentication
Get API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `grok-imagine-1.5-video-ext` - Grok Video Generation
Example: `"grok-imagine-1.5-video-ext"`
Use `grok-imagine-1.5-video-ext` consistently in new requests.
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description, supports multiple languages
Video size
Options:
* `16:9` - Landscape (default)
* `9:16` - Portrait
* `1:1` - Square
* `3:2` - Landscape
* `2:3` - Portrait
Video duration (seconds)
Range: 6-15 (minimum 6 seconds, maximum 15 seconds)
**⚠️ Note:** Must be a plain number (e.g. `6`), do not add quotes, otherwise an error will occur
Video quality
Options:
* `480p` - Standard definition (default)
* `720p` - High definition
List of reference image URLs
**Limits:**
* Maximum 7 images
* Must be publicly accessible URLs
* Base64 format is not supported
After uploading a reference image, the aspect ratio will automatically match the reference image's aspect ratio.
## Response
Response status code
Response data array
Unique task identifier
Task status
* `submitted` - Submitted
**Query Task Result**
Video generation is an async task. After submission, a `task_id` will be returned. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
## Use Cases
### Case 1: Text-to-Video
```json theme={null}
{
"model": "grok-imagine-1.5-video-ext",
"prompt": "A dog running on the beach, sunny weather, slow motion",
"size": "16:9",
"duration": 6
}
```
### Case 2: Image-to-Video
```json theme={null}
{
"model": "grok-imagine-1.5-video-ext",
"prompt": "Bring the scene to life with natural dynamic effects",
"image_urls": ["https://example.com/start.png"],
"size": "16:9",
"duration": 10,
"resolution": "720p"
}
```
# Grok Official Video Models
Source: https://docs.apimart.ai/en/api-reference/videos/grok-imagine/official
POST https://api.apimart.ai/v1/videos/generations
Generate videos from text or reference images with grok-imagine-video and grok-imagine-video-1.5, or edit a source video with the base model.
This page covers the official models `grok-imagine-video` and `grok-imagine-video-1.5`. They are separate from `grok-imagine-1.5-video-ext` on the existing generation page; do not mix their model names or parameters.
Never expose an API key in a browser bundle, public environment variable, LocalStorage, URL, or frontend logs. Call APIMart through your backend or BFF.
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Idempotency-Key: 7d0141e4-a19a-4650-a717-dab777b3a330' \
--data '{
"model": "grok-imagine-video",
"prompt": "A cinematic aerial shot of a coastal city at sunrise",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9",
"nsfw_check": true
}'
```
```javascript JavaScript theme={null}
const response = await fetch("https://api.apimart.ai/v1/videos/generations", {
method: "POST",
headers: {
Authorization: "Bearer ",
"Content-Type": "application/json",
Accept: "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
model: "grok-imagine-video",
prompt: "Improve motion consistency and apply cinematic color grading",
video: { url: "https://cdn.example.com/source-video.mp4" },
}),
});
console.log(response.status, await response.json());
```
```json 200 theme={null}
{
"code": 200,
"data": [{
"status": "submitted",
"task_id": "task_01M09Y4Y101HTFFPV2QPW9DQ3W"
}]
}
```
```json 400 theme={null}
{
"error": {
"message": "Invalid request parameters",
"type": "invalid_request_error",
"param": "resolution",
"code": "invalid_request_error"
}
}
```
## Integration overview
All modes use the same asynchronous endpoint:
```http theme={null}
POST https://api.apimart.ai/v1/videos/generations
```
| Request fields | Mode | Models |
| -------------------------- | ------------------------- | ------------------------- |
| No `image_urls` or `video` | Text to video | Both models |
| `image_urls` | Reference images to video | Both models |
| `video` | Video editing | `grok-imagine-video` only |
After submission, save `data[0].task_id`, then poll:
```http theme={null}
GET https://api.apimart.ai/v1/tasks/{task_id}
```
Do not send `X-APIMart-Response-Version`. It switches to an HTTP `202` response schema; this page uses the legacy HTTP `200` asynchronous task response.
## Model capabilities
| Capability | `grok-imagine-video` | `grok-imagine-video-1.5` |
| ----------------------------------- | :------------------: | :----------------------: |
| Text to video | ✅ | ✅ |
| Single or multiple reference images | ✅ | ✅ |
| Video editing | ✅ | ❌ |
| `480p` | ✅ | ✅ |
| `720p` | ✅ | ✅ |
| `1080p` | ❌ | ✅ |
| Duration: 1–15 seconds | 1–15 | 1–15 |
| Prompt | 1–8000 | 1–8000 |
```text theme={null}
duration = 8
resolution = 480p
aspect_ratio = auto
```
The public contract does not define a fixed reference-image count limit. Keep a non-empty array of valid URLs in their original order; do not reuse image-model limits.
## Request headers
`Bearer `
Always use `application/json`.
`application/json`
`Idempotency-Key` is optional and strongly recommended for paid generation and editing. It accepts 1–191 visible ASCII characters; UUID is recommended. Reuse the original key and identical body for a network retry. Do not switch keys when the result is uncertain.
Use a new key for each new logical operation. A retry of the same operation must reuse the original key and identical body.
## Request parameters
### Common fields
Official model name; video editing supports the base model only
* `grok-imagine-video`
* `grok-imagine-video-1.5`
Non-empty instruction, at most 8000 Unicode characters
`Array.from(prompt).length`
Whether to perform content moderation before submitting the video task.
* `true`: Use `omni-moderation-latest` to review the prompt and input images
* `false` or omitted: Do not send a moderation request, adding no moderation cost or latency (default)
### Generation fields
Generation only; integer from 1 to 15, default 8
Base: `480p/720p`; 1.5: `480p/720p/1080p`; default `480p`
* `grok-imagine-video`: `480p`, `720p`
* `grok-imagine-video-1.5`: `480p`, `720p`, `1080p`
Generation only; `auto`, `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2`, or `2:3`
* `auto`
* `1:1`, `16:9`, `9:16`
* `4:3`, `3:4`, `3:2`, `2:3`
Optional reference-image array; every item must be a public HTTPS URL; omit instead of sending an empty array
* Every item must be a publicly accessible HTTPS URL; relative URLs, Data URLs, and raw Base64 are not supported.
* Do not send aliases such as `image`, `images`, or `input_reference`.
* Array order is preserved; duplicate URLs occupy multiple input slots and may be billed more than once.
### Video-edit fields
Source video object `{url}`; public HTTPS URL; base model only
HTTPS
A video-edit request requires `model`, `prompt`, and `video`, and may optionally include `nsfw_check`. Do not send `duration`, `resolution`, `aspect_ratio`, or `image_urls`; the platform detects the source duration.
## TypeScript request types
Use a discriminated union so generation-only fields cannot be sent to video editing.
```ts theme={null}
type GrokVideoModel =
| "grok-imagine-video"
| "grok-imagine-video-1.5";
type GrokVideoResolution = "480p" | "720p" | "1080p";
type GrokVideoAspectRatio =
| "auto"
| "1:1"
| "16:9"
| "9:16"
| "4:3"
| "3:4"
| "3:2"
| "2:3";
interface GrokVideoGenerateRequest {
model: GrokVideoModel;
prompt: string;
nsfw_check?: boolean;
duration?: number;
resolution?: GrokVideoResolution;
aspect_ratio?: GrokVideoAspectRatio;
image_urls?: string[];
}
interface GrokVideoEditRequest {
model: "grok-imagine-video";
prompt: string;
nsfw_check?: boolean;
video: { url: string };
}
type GrokVideoRequest =
| GrokVideoGenerateRequest
| GrokVideoEditRequest;
```
## Request examples
```json theme={null}
{"model":"grok-imagine-video","prompt":"A cinematic aerial shot at sunrise","duration":5,"resolution":"720p","aspect_ratio":"16:9"}
```
```json theme={null}
{"model":"grok-imagine-video-1.5","prompt":"A smooth studio product commercial","duration":5,"resolution":"1080p","aspect_ratio":"16:9"}
```
```json theme={null}
{
"model":"grok-imagine-video-1.5",
"prompt":"Use the first image as subject and the second as style",
"duration":5,
"resolution":"720p",
"aspect_ratio":"16:9",
"image_urls":[
"https://cdn.example.com/subject.jpg",
"https://cdn.example.com/style.jpg"
]
}
```
```json theme={null}
{
"model":"grok-imagine-video",
"prompt":"Improve motion consistency and apply cinematic color grading",
"video":{"url":"https://cdn.example.com/source.mp4"}
}
```
## Asynchronous tasks
### Create success
A successful create request returns HTTP `200`. Save `data[0].task_id`; submission does not mean the video is complete. A task ID means submitted, not completed.
```json theme={null}
{
"code":200,
"data":[{"status":"submitted","task_id":"task_01M09Y4Y101HTFFPV2QPW9DQ3W"}]
}
```
### Query a task
```http theme={null}
GET https://api.apimart.ai/v1/tasks/{task_id}
Authorization: Bearer
Accept: application/json
```
Poll `GET /v1/tasks/{task_id}` every 3–5 seconds. Resume polling with the saved task ID after a page refresh.
| `data.status` | Meaning | Frontend action |
| ------------- | ------------------- | ---------------------------------------- |
| `pending` | Queued | Continue polling |
| `processing` | Generating | Show progress and continue |
| `completed` | Completed | Read the result and stop |
| `failed` | Failed and refunded | Show the error and stop |
| `unknown` | Temporarily unknown | Reduce polling frequency and retry later |
### Completed response
```json theme={null}
{
"code":200,
"data":{
"id":"task_xxx",
"status":"completed",
"progress":100,
"created":1787040038,
"completed":1787040081,
"actual_time":43,
"estimated_time":100,
"cost":0.072,
"credits_cost":0.72,
"result":{"videos":[{"url":["https://cdn.example.com/result.mp4"],"expires_at":1787126481}]}
}
}
```
`result.videos[0].url` is an array of strings, not a single string. Validate every value as an HTTPS URL before display. Runtime validation is recommended:
```ts theme={null}
function extractVideoURLs(payload: unknown): string[] {
const groups = (payload as any)?.data?.result?.videos;
if (!Array.isArray(groups)) return [];
return groups.flatMap((group: any) =>
Array.isArray(group?.url)
? group.url.filter(
(url: unknown): url is string =>
typeof url === "string" && /^https:///i.test(url),
)
: [],
);
}
```
Use `expires_at` as the source of truth for URL expiry. Do not hard-code a lifetime; prompt users to download or persist the result.
### Failed response
```json theme={null}
{
"code":200,
"data":{
"id":"task_xxx",
"status":"failed",
"progress":100,
"cost":0,
"credits_cost":0,
"error":{"message":"Task failed.","type":"task_failed","param":"","code":"task_failed"}
}
}
```
A task query can return HTTP `200` while `data.status` is `failed`. Determine success from `data.status`; failed tasks have `cost=0`.
## Pricing catalog
```http theme={null}
GET https://api.apimart.ai/api/pricing/models/all
```
Read `GET /api/pricing/models/all` and find the model by `id` in `data.models.video`. Prices are estimates; the authoritative final amount is `data.cost` from the task response.
### Output-video pricing
```json theme={null}
{
"fixed_prices":{
"unit":"usd_per_second",
"dimension":"resolution",
"items":[
{"key":"480P","original_price":0.05,"after_discount":0.04},
{"key":"720P","original_price":0.07,"after_discount":0.056}
]
}
}
```
* Pricing keys use uppercase `480P/720P/1080P`, while request values use lowercase; normalize case when looking up prices.
* `default` is compatibility metadata, not a selectable resolution.
* Use `after_discount` directly; do not apply the discount again.
### Input-material pricing
```json theme={null}
{"unit":"usd_per_image","original_price":0.002,"after_discount":0.0016}
```
```json theme={null}
{"unit":"usd_per_second","original_price":0.01,"after_discount":0.008}
```
Video input pricing is a scalar object. Do not require `items`, `billing_mode`, or `max_billable_seconds`. Model 1.5 has no video-input price because it cannot edit video.
### Estimate formulas
```text theme={null}
Generation estimate = discounted output price per second × duration + discounted image price × image count
Edit estimate = discounted 720P output price per second × source seconds + discounted video-input price × source seconds
```
User-specific pricing and server-side rounding can change the estimate. The final amount is always task `data.cost`.
## Frontend rules
### Model switching
* Base model shows only `480p/720p`; 1.5 also shows `1080p`.
* Switching from 1.5 `1080p` to base must fall back to `480p`.
* Video-edit mode fixes the model to `grok-imagine-video`.
### Mode switching
| Mode | Visible controls | Submitted fields | Must clear |
| ---------------- | ---------------------------------------------------- | -------------------------------- | --------------------------------------------- |
| Generation | `prompt/duration/resolution/aspect_ratio/nsfw_check` | Generation fields | `image_urls/video` |
| Reference images | Generation fields + `image_urls` | Generation fields + `image_urls` | `video` |
| Video editing | `prompt/video/nsfw_check` | `model/prompt/video/nsfw_check` | `duration/resolution/aspect_ratio/image_urls` |
`nsfw_check` is optional in every mode. Send `true` when moderation is enabled; omit it or send `false` when disabled.
Disable the run button when any of these conditions applies:
* Text mode omits `image_urls` and `video`.
* Reference mode sends `image_urls` and omits `video`.
* Video-edit mode clears all generation-only fields.
* Disable submission for an empty or over-limit prompt, invalid duration, unsupported resolution, invalid material URL, active upload, or duplicate submission.
* Limit prompts to 8000 Unicode characters and duration to integers from 1 to 15.
* Use public HTTPS URLs only; omit empty `image_urls`.
## Common errors
| HTTP / Status | Common cause | Handling |
| ------------- | ------------------------------------------------------ | ------------------------------------------------------ |
| `400` | Invalid parameters, prompt limit, or unsupported enum | Show the server message and identify the field |
| `401` | Missing or invalid API key | Do not retry; check server configuration |
| `402` | Insufficient balance | Prompt the user to top up |
| `403` | Missing model permission | Do not retry automatically |
| `409` | Idempotency conflict or original request still running | Keep the original key and retry the same request later |
| `429` | Rate limit | Honor `Retry-After` or use exponential backoff |
| `500/502/503` | Temporary service failure | Retry a bounded number of times with the original key |
| `failed` | Asynchronous task failure | Stop polling, show the error; cost is zero |
## Frontend checklist
* Keep the API key only in the backend or BFF.
* Do not mix official model names with `grok-imagine-1.5-video-ext`.
* Limit prompts to 8000 Unicode characters and duration to integers from 1 to 15.
* Use public HTTPS URLs only; omit empty `image_urls`.
* Send only `model/prompt/video` plus optional `nsfw_check` for video editing, and use the base model.
* Read `data[0].task_id` on submit and determine the terminal state from `data.status`.
* Read output from `result.videos[].url[]` and respect `expires_at`.
* Use catalog prices for display and task `data.cost` for the final amount.
# HappyHorse 1.0 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/happyhorse-1.0/generation
POST https://api.apimart.ai/v1/videos/generations
- Alibaba Cloud Bailian HappyHorse 1.0 video generation model (unified entry, single-model auto-routing)
- Auto-routes by parameters: T2V (prompt only) / I2V (first_frame_image) / R2V (image_urls) / EDIT (video_url)
- Supports 720P/1080P resolutions and any integer duration from 3 to 15 seconds
- Billed by resolution × duration (seconds) only, regardless of capability
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "happyhorse-1.0",
"prompt": "A little girl walking down the road, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 5,
"seed": 42
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "happyhorse-1.0",
"prompt": "A little girl walking down the road, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 5,
"seed": 42
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "happyhorse-1.0",
prompt: "A little girl walking down the road, cinematic feel",
resolution: "1080P",
size: "16:9",
duration: 5,
seed: 42
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "happyhorse-1.0",
"prompt": "A little girl walking down the road, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 5,
"seed": 42,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "happyhorse-1.0",
"prompt": "A little girl walking down the road, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 5,
"seed": 42
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"happyhorse-1.0",
"prompt" => "A little girl walking down the road, cinematic feel",
"resolution" => "1080P",
"size" => "16:9",
"duration" => 5,
"seed" => 42
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "happyhorse-1.0",
prompt: "A little girl walking down the road, cinematic feel",
resolution: "1080P",
size: "16:9",
duration: 5,
seed: 42
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "happyhorse-1.0",
"prompt": "A little girl walking down the road, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 5,
"seed": 42
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""happyhorse-1.0"",
""prompt"": ""A little girl walking down the road, cinematic feel"",
""resolution"": ""1080P"",
""size"": ""16:9"",
""duration"": 5,
""seed"": 42
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Mode Routing
`happyhorse-1.0` is the unified entry for Text-to-Video / Image-to-Video / Reference-Image-to-Video / Video Edit. The backend automatically determines the mode based on incoming parameters. **All modes are billed by the same rule (resolution × seconds only)**:
| Fields you pass | Routes To | Mode Description |
| ---------------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------ |
| `prompt` only | Text-to-Video (T2V) | Generate video purely from text |
| `prompt` + `first_frame_image` | Image-to-Video (I2V) | Animate from a first-frame image |
| `prompt` + `image_urls` (1–9 images) | Reference-Image-to-Video (R2V) | Generate a new scene from reference images |
| `prompt` + `video_url` (optional `image_urls` 0–5 as style refs / `audio_setting`) | Video Edit (EDIT) | Rewrite / restylize a source video |
**Routing priority** (high to low): `video_url` > `first_frame_image` > `image_urls` > `prompt` only.
**Mutual exclusion rules**: the three media fields (`first_frame_image` / `image_urls` / `video_url`) are **mutually exclusive in pairs**. The only valid combination is `video_url + image_urls` (EDIT mode + reference images). Passing two mutually exclusive fields returns 400 `mixed_media_not_allowed`.
## Request Parameters
Video generation model name, fixed as `happyhorse-1.0`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description, up to 2500 characters; cannot contain special tokens
* **T2V / R2V / EDIT modes**: required
* **I2V mode**: optional, but recommended to guide camera movement and actions
Example: `"A little girl walking down the road, cinematic feel"`
First-frame image, triggers **I2V** (Image-to-Video). Supports URL or base64 (`data:image/;base64,`, the gateway uploads it to OSS automatically)
Mutually exclusive with `image_urls` / `video_url`
**First-frame image requirements:**
* Format: JPEG / JPG / PNG / BMP / WEBP
* Short side: ≥ 300px
* Aspect ratio: `1:2.5` to `2.5:1`
* File size: ≤ 10MB
Image array:
* **R2V mode** (only `image_urls` provided): 1–9 images, used as subject/style references to generate a new scene
* **EDIT mode** (provided together with `video_url`): 0–5 images, used as style reference
Supports URL or base64
Mutually exclusive with `first_frame_image`; can be combined with `video_url`
**Reference image requirements:**
* Format: JPEG / JPG / PNG / BMP / WEBP
* Short side: ≥ 720p recommended
* Aspect ratio: short / long ≥ 0.4
* File size: ≤ 10MB
* Count: R2V must be 1–9; EDIT up to 5
Source video URL, triggers **EDIT** (Video Edit). **Base64 is not supported** — provide an HTTP/HTTPS direct link
Mutually exclusive with `first_frame_image`; can be combined with `image_urls` (≤ 5)
**Source video requirements:**
* Duration: 3–60 seconds (> 15s will be auto-truncated by the upstream from 0 to 15s)
* Resolution: minimum 480p, short side ≥ 360
* Aspect ratio: `1:8` to `8:1`
* Format: MP4 / MOV (H.264 recommended)
* Frame rate: > 8 fps
* File size: ≤ 100MB
**In EDIT mode, the generated video's duration matches the source video** (capped at the truncated 15s when the source is longer). The `duration` parameter has no effect here. To control the output length, trim the source video to the target duration before uploading.
Audio setting, **only effective in EDIT mode** (must pass `video_url`)
Options:
* `auto` - Auto-generate audio (default)
* `origin` - Keep the source video's audio track
Passing this field outside EDIT mode returns 400 `audio_setting_only_for_edit`
Video resolution (affects billing)
Options:
* `720P` - Standard
* `1080P` - High definition (default)
Video duration in seconds (affects billing)
Supported range: any integer from `3` to `15`
Default: `5`
**Has no effect in EDIT mode (when `video_url` is provided)**: the generated video's duration matches the source video (billed by the truncated 15s when the source is longer than 15s). To control the output length, trim the source video first.
Aspect ratio
Supported formats:
* `16:9` - Landscape widescreen (default)
* `9:16` - Portrait
* `1:1` - Square
* `4:3` - Landscape
* `3:4` - Portrait
**Ignored in I2V / EDIT modes** — the output aspect ratio is determined automatically by the input media (first-frame image / source video)
Whether to add a watermark to the generated video
* `true`: Add watermark
* `false`: Do not add watermark (default)
Random seed used to control the randomness of generated content
Value range: `[0, 2147483647]`. If omitted, a random seed is used.
* For identical requests, the model generates different results when receiving different seed values (e.g., omitting seed)
* For identical requests, the model generates similar results when receiving the same seed value, but exact consistency is not guaranteed
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video T2V (Simplest Request)
```json theme={null}
{
"model": "happyhorse-1.0",
"prompt": "A little girl walking down the road, cinematic feel"
}
```
### Case 2: Text-to-Video T2V (Full Parameters)
```json theme={null}
{
"model": "happyhorse-1.0",
"prompt": "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 8,
"seed": 42
}
```
### Case 3: Image-to-Video I2V (first\_frame\_image)
```json theme={null}
{
"model": "happyhorse-1.0",
"prompt": "Bring the scene in the image to life",
"first_frame_image": "https://example.com/first_frame.png",
"resolution": "1080P",
"duration": 5
}
```
### Case 4: Reference-Image-to-Video R2V (multiple references)
```json theme={null}
{
"model": "happyhorse-1.0",
"prompt": "The protagonist from image 1 runs through the scene from image 2, then picks up the prop from image 3. Keep a 3D cartoon style with smooth motion.",
"image_urls": [
"https://example.com/img_01.jpg",
"https://example.com/img_02.png",
"https://example.com/img_03.jpeg"
],
"resolution": "1080P",
"size": "16:9",
"duration": 5
}
```
### Case 5: Video Edit EDIT (keep original audio + style reference)
```json theme={null}
{
"model": "happyhorse-1.0",
"prompt": "Convert the character in the video to a cartoon style, preserving the original motion",
"video_url": "https://example.com/source.mp4",
"image_urls": [
"https://example.com/style_ref.jpg"
],
"resolution": "1080P",
"audio_setting": "origin",
"seed": 42
}
```
### Case 6: 720P to Save Cost
```json theme={null}
{
"model": "happyhorse-1.0",
"prompt": "Waves crashing on the beach at sunset",
"resolution": "720P",
"size": "16:9",
"duration": 5
}
```
## Mode Selection Guide
| Requirement | Recommended Approach |
| ------------------------------------------------------ | --------------------------------------------------------------------------------- |
| Generate video from text only | Pass only `prompt` (T2V) |
| Make an image "come alive" (use it as the first frame) | Pass `first_frame_image` (I2V) |
| Generate a new scene from a set of reference images | Pass `image_urls` (1–9, R2V) |
| Rewrite / restylize an existing video | Pass `video_url` (EDIT), optionally combine with `image_urls` (0–5) as style refs |
| Save cost | Use `resolution: "720P"` |
## Usage Tips
1. **Unified entry logic**: input fields decide the mode. Note that the three media fields (`first_frame_image` / `image_urls` / `video_url`) are mutually exclusive in pairs
2. **`size` only effective in T2V/R2V**: in I2V / EDIT modes `size` is ignored — the output aspect ratio is determined by the input media
3. **Duration**: 5–10 seconds is the sweet spot. Too short causes choppy motion; too long significantly increases upstream processing time
4. **First-frame image quality**: clear, well-composed, subject centered — significantly improves I2V output
5. **Prompt writing**: describe motion / camera / atmosphere (e.g., "slow push-in, cinematic, warm tones") for better results than purely static scene descriptions
6. **EDIT input video**: > 15 seconds will be auto-truncated by the upstream from 0 to 15s. If you need other segments, slice the video yourself first
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# HappyHorse 1.1 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/happyhorse-1.1/generation
POST https://api.apimart.ai/v1/videos/generations
- Alibaba Cloud Bailian HappyHorse 1.1 video generation model (unified entry, single-model auto-routing)
- Auto-routes by parameters: T2V (prompt only) / I2V (first_frame_image) / R2V (image_urls)
- Supports 720P/1080P resolutions and any integer duration from 3 to 15 seconds
- Billed by resolution × duration (seconds) only, regardless of capability
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "happyhorse-1.1",
"prompt": "A little girl walking down the road, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 5,
"seed": 42
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "happyhorse-1.1",
"prompt": "A little girl walking down the road, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 5,
"seed": 42
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "happyhorse-1.1",
prompt: "A little girl walking down the road, cinematic feel",
resolution: "1080P",
size: "16:9",
duration: 5,
seed: 42
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "happyhorse-1.1",
"prompt": "A little girl walking down the road, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 5,
"seed": 42,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "happyhorse-1.1",
"prompt": "A little girl walking down the road, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 5,
"seed": 42
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"happyhorse-1.1",
"prompt" => "A little girl walking down the road, cinematic feel",
"resolution" => "1080P",
"size" => "16:9",
"duration" => 5,
"seed" => 42
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "happyhorse-1.1",
prompt: "A little girl walking down the road, cinematic feel",
resolution: "1080P",
size: "16:9",
duration: 5,
seed: 42
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "happyhorse-1.1",
"prompt": "A little girl walking down the road, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 5,
"seed": 42
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""happyhorse-1.1"",
""prompt"": ""A little girl walking down the road, cinematic feel"",
""resolution"": ""1080P"",
""size"": ""16:9"",
""duration"": 5,
""seed"": 42
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Mode Routing
`happyhorse-1.1` is the unified entry for Text-to-Video / Image-to-Video / Reference-Image-to-Video. The backend automatically determines the mode based on incoming parameters. **All modes are billed by the same rule (resolution × seconds only)**:
| Fields you pass | Routes To | Mode Description |
| ------------------------------------ | ------------------------------ | ------------------------------------------ |
| `prompt` only | Text-to-Video (T2V) | Generate video purely from text |
| `prompt` + `first_frame_image` | Image-to-Video (I2V) | Animate from a first-frame image |
| `prompt` + `image_urls` (1–9 images) | Reference-Image-to-Video (R2V) | Generate a new scene from reference images |
**Routing priority** (high to low): `first_frame_image` > `image_urls` > `prompt` only.
**Mutual exclusion rules**: the two media fields (`first_frame_image` / `image_urls`) are **mutually exclusive**. Passing both mutually exclusive fields returns 400 `mixed_media_not_allowed`.
## Request Parameters
Video generation model name, fixed as `happyhorse-1.1`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description, up to 2500 characters; cannot contain special tokens
Example: `"A little girl walking down the road, cinematic feel"`
First-frame image, triggers **I2V** (Image-to-Video). Supports URL or base64 (`data:image/;base64,`, the gateway uploads it to OSS automatically)
Mutually exclusive with `image_urls`
**First-frame image requirements:**
* Format: JPEG / JPG / PNG / BMP / WEBP
* Short side: ≥ 300px
* Aspect ratio: `1:2.5` to `2.5:1`
* File size: ≤ 10MB
Image array (**R2V mode**): 1–9 images, used as subject/style references to generate a new scene
Supports URL or base64
Mutually exclusive with `first_frame_image`
**Reference image requirements:**
* Format: JPEG / JPG / PNG / BMP / WEBP
* Short side: ≥ 720p recommended
* Aspect ratio: short / long ≥ 0.4
* File size: ≤ 10MB
* Count: 1–9 images
Video resolution (affects billing)
Options:
* `720P` - Standard
* `1080P` - High definition (default)
Video duration in seconds (affects billing)
Supported range: any integer from `3` to `15`
Default: `5`
Aspect ratio
Supported formats:
* `16:9` - Landscape widescreen (default)
* `9:16` - Portrait
* `1:1` - Square
* `4:3` - Landscape
* `3:4` - Portrait
**Ignored in I2V mode** — the output aspect ratio is determined automatically by the input media (first-frame image)
Whether to add a watermark to the generated video
* `true`: Add watermark
* `false`: Do not add watermark (default)
Random seed used to control the randomness of generated content
Value range: `[0, 2147483647]`. If omitted, a random seed is used.
* For identical requests, the model generates different results when receiving different seed values (e.g., omitting seed)
* For identical requests, the model generates similar results when receiving the same seed value, but exact consistency is not guaranteed
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video T2V (Simplest Request)
```json theme={null}
{
"model": "happyhorse-1.1",
"prompt": "A little girl walking down the road, cinematic feel"
}
```
### Case 2: Text-to-Video T2V (Full Parameters)
```json theme={null}
{
"model": "happyhorse-1.1",
"prompt": "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
"resolution": "1080P",
"size": "16:9",
"duration": 8,
"seed": 42
}
```
### Case 3: Image-to-Video I2V (first\_frame\_image)
```json theme={null}
{
"model": "happyhorse-1.1",
"prompt": "Bring the scene in the image to life",
"first_frame_image": "https://example.com/first_frame.png",
"resolution": "1080P",
"duration": 5
}
```
### Case 4: Reference-Image-to-Video R2V (multiple references)
```json theme={null}
{
"model": "happyhorse-1.1",
"prompt": "The protagonist from image 1 runs through the scene from image 2, then picks up the prop from image 3. Keep a 3D cartoon style with smooth motion.",
"image_urls": [
"https://example.com/img_01.jpg",
"https://example.com/img_02.png",
"https://example.com/img_03.jpeg"
],
"resolution": "1080P",
"size": "16:9",
"duration": 5
}
```
### Case 5: 720P to Save Cost
```json theme={null}
{
"model": "happyhorse-1.1",
"prompt": "Waves crashing on the beach at sunset",
"resolution": "720P",
"size": "16:9",
"duration": 5
}
```
## Mode Selection Guide
| Requirement | Recommended Approach |
| ------------------------------------------------------ | ------------------------------ |
| Generate video from text only | Pass only `prompt` (T2V) |
| Make an image "come alive" (use it as the first frame) | Pass `first_frame_image` (I2V) |
| Generate a new scene from a set of reference images | Pass `image_urls` (1–9, R2V) |
| Save cost | Use `resolution: "720P"` |
## Usage Tips
1. **Unified entry logic**: input fields decide the mode. Note that the two media fields (`first_frame_image` / `image_urls`) are mutually exclusive
2. **`size` only effective in T2V/R2V**: in I2V mode `size` is ignored — the output aspect ratio is determined by the input media
3. **Duration**: 5–10 seconds is the sweet spot. Too short causes choppy motion; too long significantly increases upstream processing time
4. **First-frame image quality**: clear, well-composed, subject centered — significantly improves I2V output
5. **Prompt writing**: describe motion / camera / atmosphere (e.g., "slow push-in, cinematic, warm tones") for better results than purely static scene descriptions
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Kling 3.0 Turbo Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/kling-3.0-turbo/generation
POST https://api.apimart.ai/v1/videos/generations
- Asynchronous processing mode, returns a task ID for subsequent queries
- Supports text-to-video and image-to-video (first-frame control)
- Supports two resolution tiers: 720P / 1080P
- Supports video durations of 3-15 seconds
- Supports multi-shot storyboards (expressed via a fixed-format prompt)
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-3.0-turbo",
"prompt": "A corgi running on the beach, cinematic, golden-hour light",
"aspect_ratio": "16:9",
"resolution": "1080p",
"duration": 5
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "kling-3.0-turbo",
"prompt": "A corgi running on the beach, cinematic, golden-hour light",
"aspect_ratio": "16:9",
"resolution": "1080p",
"duration": 5
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "kling-3.0-turbo",
prompt: "A corgi running on the beach, cinematic, golden-hour light",
aspect_ratio: "16:9",
resolution: "1080p",
duration: 5
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "kling-3.0-turbo",
"prompt": "A corgi running on the beach, cinematic, golden-hour light",
"aspect_ratio": "16:9",
"resolution": "1080p",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "kling-3.0-turbo",
"prompt": "A corgi running on the beach, cinematic, golden-hour light",
"aspect_ratio": "16:9",
"resolution": "1080p",
"duration": 5
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"kling-3.0-turbo",
"prompt" => "A corgi running on the beach, cinematic, golden-hour light",
"aspect_ratio" => "16:9",
"resolution" => "1080p",
"duration" => 5
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "kling-3.0-turbo",
prompt: "A corgi running on the beach, cinematic, golden-hour light",
aspect_ratio: "16:9",
resolution: "1080p",
duration: 5
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "kling-3.0-turbo",
"prompt": "A corgi running on the beach, cinematic, golden-hour light",
"aspect_ratio": "16:9",
"resolution": "1080p",
"duration": 5
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""kling-3.0-turbo"",
""prompt"": ""A corgi running on the beach, cinematic, golden-hour light"",
""aspect_ratio"": ""16:9"",
""resolution"": ""1080p"",
""duration"": 5
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_xxxxxxxxxx"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
## Authentication
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to obtain your API Key
Add it to the request header when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `kling-3.0-turbo` - Kling 3.0 Turbo
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text prompt
The upstream limit is no more than 3072 characters; we recommend no more than 2500 characters.
Example: `"A corgi running on the beach, cinematic, golden-hour light"`
Supports an **image URL** or **Base64**.
Upstream limits for the first-frame image:
* Format: `.jpg` / `.jpeg` / `.png`
* Size: ≤ 50MB
* Width/height: ≥ 300px
* Aspect ratio: `1:2.5` \~ `2.5:1`
Video aspect ratio
Available values:
* `16:9` - Landscape
* `9:16` - Portrait
* `1:1` - Square
Default value: `16:9`
**Only effective for text-to-video**. This field has no effect for image-to-video; the video ratio is determined by the first-frame image.
Video resolution
Available values:
* `720p`
* `1080p`
Default value: `720p`
Video duration (seconds)
Value range: 3-15 (minimum 3 seconds, maximum 15 seconds)
Default value: `5`
**⚠️ Note:** You must enter a plain number (e.g. `6`); do not add quotes, otherwise it will cause an error
Whether to add a watermark
Only passed to the upstream when explicitly provided; if omitted, no watermark is added.
## Text-to-Video vs Image-to-Video
The system **automatically determines** the generation mode based on whether `first_frame_image` is provided: with a first-frame image it uses image-to-video, without one it uses text-to-video. Users do not need to declare it explicitly.
| Parameter | Text-to-Video | Image-to-Video |
| ------------------- | ----------------- | ------------------------------------------------------------------ |
| `prompt` | ✅ Required | ✅ Optional (if empty, generated purely from the first-frame image) |
| `first_frame_image` | ❌ Not passed | ✅ Required |
| `aspect_ratio` | ✅ Optional | ❌ No effect (ratio determined by the first-frame image) |
| `resolution` | ✅ Optional | ✅ Optional |
| `duration` | ✅ Optional (3-15) | ✅ Optional (3-15) |
| `watermark` | ✅ Optional | ✅ Optional |
## Response
Response status code, 200 on success
Returned data array
Task status, `submitted` upon initial submission
Unique task identifier, used to query the task status and result
## Use Cases
### Scenario 1: Text-to-Video (1080P)
```json theme={null}
{
"model": "kling-3.0-turbo",
"prompt": "A corgi running on the beach, cinematic, golden-hour light",
"aspect_ratio": "16:9",
"resolution": "1080p",
"duration": 5
}
```
### Scenario 2: Text-to-Video (Portrait 720P)
```json theme={null}
{
"model": "kling-3.0-turbo",
"prompt": "Shibuya crossing in Tokyo, neon lights on a rainy night reflecting on the wet ground, pedestrians walking through with umbrellas",
"aspect_ratio": "9:16",
"resolution": "720p",
"duration": 10
}
```
### Scenario 3: Image-to-Video (First-Frame Image)
```json theme={null}
{
"model": "kling-3.0-turbo",
"prompt": "The camera slowly pushes in, the character smiles",
"first_frame_image": "https://cdn.example.com/first.jpg",
"resolution": "720p",
"duration": 5
}
```
### Scenario 4: Image-to-Video from First Frame Only (No Prompt)
```json theme={null}
{
"model": "kling-3.0-turbo",
"first_frame_image": "https://cdn.example.com/first.jpg",
"resolution": "1080p",
"duration": 5
}
```
### Scenario 5: Multi-Shot Storyboard (Text-to-Video)
```json theme={null}
{
"model": "kling-3.0-turbo",
"prompt": "Shot 1,2,a corgi running on the beach;Shot 2,3,the camera pushes in on the character smiling;",
"aspect_ratio": "16:9",
"resolution": "1080p",
"duration": 5
}
```
**Querying the Task Result**
Video generation is an asynchronous task; after submission a `task_id` is returned. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query the generation progress and result.
# Kling 2.6 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/kling-v2-6/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns task ID for subsequent queries
- Supports text-to-video, image-to-video (first frame/first-last frame control)
- Supports standard mode (720P) and professional mode (1080P)
- Professional mode supports automatic audio generation and voice selection
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-v2-6",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "kling-v2-6",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "kling-v2-6",
prompt: "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
mode: "std",
duration: 5,
aspect_ratio: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "kling-v2-6",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "kling-v2-6",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"kling-v2-6",
"prompt" => "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode" => "std",
"duration" => 5,
"aspect_ratio" => "16:9"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "kling-v2-6",
prompt: "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
mode: "std",
duration: 5,
aspect_ratio: "16:9"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "kling-v2-6",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""kling-v2-6"",
""prompt"": ""A golden cat running on a sunlit meadow, slow motion, cinematic quality"",
""mode"": ""std"",
""duration"": 5,
""aspect_ratio"": ""16:9""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_xxxxxxxxxx"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `kling-v2-6` - Kling v2.6 (recommended)
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text prompt, maximum **2500 characters**
Describe scenes, actions, styles in detail for better generation results
Example: `"A golden cat running on a sunlit meadow, slow motion, cinematic quality"`
Generation mode
Options:
* `std` - Standard mode (720P, silent video only)
* `pro` - Professional mode (1080P, supports automatic audio generation)
Default: `std`
**Standard mode limitation**: `std` mode only supports silent video. `audio` parameter requires `pro` mode.
Video duration (seconds)
Options: `5` or `10`
Default: `5`
Video aspect ratio
Options:
* `16:9` - Landscape
* `9:16` - Portrait
* `1:1` - Square
Default: `16:9`
Negative prompt to exclude unwanted content
Example: `"blurry, low quality, distorted"`
Image URL array for image-to-video generation
* Pass **1 image**: used as first frame
* Pass **2 images**: automatically assigned as first frame + last frame (requires `mode: "pro"`)
Maximum 2 images supported
Example: `["https://example.com/first.jpg"]`
* Maximum 2 images supported
* Last frame (2 images) requires `pro` mode only; `std` mode only supports first frame (1 image)
* **Last frame and audio are mutually exclusive**: In `pro` mode, last frame (2 images) and audio (`audio: true`) cannot be used together
* In image-to-video mode, `aspect_ratio` may be overridden by the actual image ratio
Whether to automatically generate audio
Default: `false`
* Only available in `mode: "pro"`
* **Mutually exclusive with last frame**: Audio cannot be used together with last frame (2 images)
Whether to add watermark
## Feature Support Matrix
| Type | Feature | std 5s | std 10s | pro 5s | pro 10s |
| -------------- | ----------- | --------------- | --------------- | ------ | ------- |
| Text-to-Video | Generation | ✅ (silent only) | ✅ (silent only) | ✅ | ✅ |
| Text-to-Video | Auto Audio | - | - | ✅ | ✅ |
| Image-to-Video | Generation | ✅ (silent only) | ✅ (silent only) | ✅ | ✅ |
| Image-to-Video | First Frame | ✅ | ✅ | ✅ | ✅ |
| Image-to-Video | Last Frame | - | - | ✅ | ✅ |
| Image-to-Video | Auto Audio | - | - | ✅ | ✅ |
> **Note**: In `pro` mode, last frame and audio control are mutually exclusive and cannot be used together.
## Text-to-Video vs Image-to-Video
The system automatically determines the mode based on whether `image_urls` is provided: no images means text-to-video, with images means image-to-video.
| Parameter | Text-to-Video | Image-to-Video |
| ----------------- | ------------------------ | ----------------------------------------------- |
| `prompt` | ✅ Required | ✅ Required |
| `image_urls` | ❌ Not used | ✅ Required (1-2 images, last frame needs `pro`) |
| `negative_prompt` | ✅ Optional | ✅ Optional |
| `mode` | ✅ Optional | ✅ Optional |
| `duration` | ✅ Optional | ✅ Optional |
| `aspect_ratio` | ✅ Optional | ⚠️ May be overridden by image ratio |
| `audio` | ✅ Optional (needs `pro`) | ✅ Optional (needs `pro`) |
| `watermark` | ✅ Optional | ✅ Optional |
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video (Standard Mode)
```json theme={null}
{
"model": "kling-v2-6",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
```
### Case 2: Text-to-Video (Pro Mode + Negative Prompt)
```json theme={null}
{
"model": "kling-v2-6",
"prompt": "Tokyo Shibuya crossing at night, neon lights reflected on wet ground, people walking with umbrellas",
"negative_prompt": "blurry, low quality, distorted",
"mode": "pro",
"duration": 10,
"aspect_ratio": "16:9"
}
```
### Case 3: Image-to-Video (First Frame)
```json theme={null}
{
"model": "kling-v2-6",
"prompt": "The person in the frame turns and smiles",
"image_urls": ["https://example.com/portrait.jpg"],
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
```
### Case 4: Image-to-Video (First + Last Frame Control)
```json theme={null}
{
"model": "kling-v2-6",
"prompt": "City timelapse transitioning from day to night",
"image_urls": ["https://example.com/day-city.jpg", "https://example.com/night-city.jpg"],
"mode": "pro",
"duration": 5
}
```
### Case 5: Pro Mode + Auto Audio
```json theme={null}
{
"model": "kling-v2-6",
"prompt": "Waves crashing against rocks, seagulls circling in the sky, lighthouse in the distance",
"mode": "pro",
"duration": 10,
"audio": true,
"aspect_ratio": "16:9"
}
```
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Kling v2.6 Motion Control Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/kling-v2-6/kling-v2-6-motion-control-generation
POST https://api.apimart.ai/v1/videos/generations
- Kling motion control model (reference image + reference video)
- Called via unified endpoint `/v1/videos/generations`
- Supports image / video character orientation, max duration 10s / 30s respectively
- Asynchronous task — returns task_id on submission
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-v2-6-motion-control",
"prompt": "Keep the character consistent, perform a turn and wave following the reference video, cinematic lighting",
"image_url": "https://example.com/ref-image.png",
"video_url": "https://example.com/ref-video-8s.mp4",
"keep_original_sound": "yes",
"character_orientation": "image",
"mode": "std",
"watermark_info": {"enabled": false}
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "kling-v2-6-motion-control",
"prompt": "Keep the character consistent, perform a turn and wave following the reference video, cinematic lighting",
"image_url": "https://example.com/ref-image.png",
"video_url": "https://example.com/ref-video-8s.mp4",
"keep_original_sound": "yes",
"character_orientation": "image",
"mode": "std",
"watermark_info": {"enabled": False}
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "kling-v2-6-motion-control",
prompt: "Keep the character consistent, perform a turn and wave following the reference video, cinematic lighting",
image_url: "https://example.com/ref-image.png",
video_url: "https://example.com/ref-video-8s.mp4",
keep_original_sound: "yes",
character_orientation: "image",
mode: "std",
watermark_info: { enabled: false }
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Please check your API key.",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance. Please top up and try again.",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests. Please try again later.",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later.",
"type": "server_error"
}
}
```
## Authentication
All requests require Bearer Token authentication
Get your API Key:
Visit the [API Key Management page](https://apimart.ai/keys) to obtain your API Key
Add the following header to each request:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name: `kling-v3-motion-control` or `kling-v2-6-motion-control`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text prompt describing the desired motion, camera movement, and style
Optional but recommended — more specific descriptions produce more stable results
Example: `"The character dances following the reference video, smooth motion, realistic style"`
Reference image URL
Must be a publicly accessible link
Reference video URL
Must be a publicly accessible direct link; mp4/mov recommended, under 100MB
The server probes the actual duration of `video_url`. Minimum is 3 seconds; maximum is determined by `character_orientation`.
Whether to retain the original audio track from the reference video
Options:
* `yes`: Keep original audio (default)
* `no`: Do not keep original audio
Character orientation control
Options:
* `image`: Use the character orientation from the reference image (reference video duration: `3~10s`)
* `video`: Use the character orientation from the reference video (reference video duration: `3~30s`)
Generation mode
Options:
* `std`: Standard mode (balanced speed and quality)
* `pro`: High-quality mode (higher latency)
Watermark control object (optional)
Whether to add a watermark
* `true`: Add watermark
* `false`: No watermark (default)
## Duration Rules
| Condition | Allowed Reference Video Duration |
| ------------------------------- | -------------------------------- |
| `character_orientation = image` | `3s ~ 10s` |
| `character_orientation = video` | `3s ~ 30s` |
Billing duration is determined by the actual duration probed from `video_url` by the server, not a client-side estimate.
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` on initial submission
Unique task identifier used to query task status and results
## Examples
### Example 1: image orientation (within 10s)
```json theme={null}
{
"model": "kling-v2-6-motion-control",
"prompt": "Keep character orientation consistent with the reference image, perform a turn and wave",
"image_url": "https://example.com/ref-image.png",
"video_url": "https://example.com/ref-video-8s.mp4",
"character_orientation": "image",
"mode": "std",
"keep_original_sound": "yes",
"watermark_info": {"enabled": false}
}
```
### Example 2: video orientation (within 30s)
```json theme={null}
{
"model": "kling-v2-6-motion-control",
"prompt": "Follow the character orientation and rhythm of the reference video, maintain fluid motion",
"image_url": "https://example.com/ref-image.png",
"video_url": "https://example.com/ref-video-12s.mp4",
"character_orientation": "video",
"mode": "pro",
"keep_original_sound": "no",
"watermark_info": {"enabled": false}
}
```
# Kling v3 Omni Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/kling-v3-omni/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns task ID for subsequent queries
- Unified text-to-video/image-to-video interface with image reference syntax
- Supports standard mode (720P), professional mode (1080P), and 4K mode
- Reference images in prompts using image_N syntax
- Supports generating videos with audio (mutually exclusive with video_list)
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-v3-omni",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "kling-v3-omni",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "kling-v3-omni",
prompt: "Make the person in <<>> wave at the camera",
image_urls: ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
mode: "std",
duration: 5,
aspect_ratio: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "kling-v3-omni",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": []string{"https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"},
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "kling-v3-omni",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"kling-v3-omni",
"prompt" => "Make the person in <<>> wave at the camera",
"image_urls" => ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode" => "std",
"duration" => 5,
"aspect_ratio" => "16:9"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "kling-v3-omni",
prompt: "Make the person in <<>> wave at the camera",
image_urls: ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
mode: "std",
duration: 5,
aspect_ratio: "16:9"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "kling-v3-omni",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""kling-v3-omni"",
""prompt"": ""Make the person in <<>> wave at the camera"",
""image_urls"": [""https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp""],
""mode"": ""std"",
""duration"": 5,
""aspect_ratio"": ""16:9""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_xxxxxxxxxx"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `kling-v3-omni` - Kling v3 Omni (unified interface)
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Positive text prompt
Supports referencing images from `image_urls` using `<<>>` syntax, where `N` starts from 1.
Example: `"Make the person in <<>> wave at the camera"`
If images are provided but the prompt does not contain any `<<>>` reference, the system will automatically prepend `<<>>` to the prompt.
Negative prompt used to exclude unwanted content. Maximum length is 2500 characters.
Generation mode
Options:
* `std` - Standard mode (720P)
* `pro` - Professional mode (1080P)
* `4k` - 4K ultra HD mode
Default: `std`
Default: `5`
Video duration (seconds)
Range: 3-15 (minimum 3 seconds, maximum 15 seconds)
**⚠️ Note:** Must be a plain number (e.g. `6`), do not add quotes, otherwise an error will occur
Video aspect ratio
Options:
* `16:9` - Landscape
* `9:16` - Portrait
* `1:1` - Square
Default: `16:9`
Image URL array for image referencing
Reference corresponding images in the prompt using `<<>>` syntax (N starts from 1)
Example: `["https://example.com/photo.jpg"]`
* Image URLs must be publicly accessible without hotlink protection
* In image-to-video mode, `aspect_ratio` may be overridden by the actual image ratio
Role-based image array, recommended for image-to-video.
Each item format: `{ "url": "...", "role": "..." }`
* `first_frame`: first frame
* `last_frame`: last frame
* `reference`: reference image
`image_urls` and `image_with_roles` are mutually exclusive. Use only one.
Reference video list (URL-based), up to 1 video.
Use `refer_type` to distinguish types:
* `base`: video to be edited (default)
* `feature`: feature reference video
Use `keep_original_sound` to control original audio:
* `no`: do not keep (default)
* `yes`: keep original sound
Request format:
```json theme={null}
"video_list":[
{ "video_url": "video_url", "refer_type": "base", "keep_original_sound": "no" }
]
```
* `video_url` cannot be empty, and the video URL must be accessible
* When `refer_type=base`:
* Start/end frames cannot be defined
* Reference video must be 3-10 seconds
* Generated video duration follows the uploaded video
* When `refer_type=feature` and `video_url` is not empty:
* `image_urls` can only include a first-frame image
* Video requirements: MP4/MOV only; duration at least 3 seconds; resolution 720px-2160px; frame rate 24-60fps (output is 24fps); size no more than 200MB
Whether to enable multi-shot mode.
Shot split method: `customize` / `intelligence`.
Required when `multi_shot=true`.
Multi-shot list, each item is `{ index, prompt, duration }`.
* Minimum 1 shot, maximum 6 shots
* Each shot `duration` must be an integer and >= 1
* Sum of all shot durations must equal top-level `duration`
* `index` must start from 1 and increase continuously
* Required when `multi_shot=true` and `shot_type=customize`
Example:
```json theme={null}
[
{ "index": 1, "prompt": "a happy dog in running@element_cat", "duration": 3 },
{ "index": 2, "prompt": "a happy dog play with a cat@element_dog", "duration": 3 }
]
```
Reference subject list, up to 3 subjects. Supports:
* Create subjects on the fly with `name`, `description`, `element_input_urls`
Common format:
```json theme={null}
[
{
"name": "element_dog",
"description": "a golden retriever, fluffy fur, friendly expression",
"element_input_urls": [
"https://example.com/image1.png",
"https://example.com/image2.png"
]
},
{
"name": "element_cat",
"description": "an orange tabby cat, round face, bright eyes",
"element_input_urls": [
"https://example.com/image1.png",
"https://example.com/image2.png"
]
}
]
```
Notes:
* For on-the-fly creation, `name`, `description`, `element_input_urls` are required
* `element_input_urls`: 2 to 4 images per subject (first as frontal image, others as references)
* Use `@name` in `prompt`, e.g. `"@element_dog and @element_cat are playing on the grass"`
Whether to add watermark
Whether to generate video with audio
This parameter is mutually exclusive with `video_list`.
When `video_list` has a value, the `audio` parameter is not needed.
### Parameter Constraints and Boundaries
* `image_urls` and `image_with_roles` are mutually exclusive
* `mode=4k` is available for `kling-v3-omni`
* Last-frame-only input (`last_frame` without first frame) is invalid
* Start/end frames and video edit are mutually exclusive: when `video_list.refer_type=base` (or omitted), start/end frames are not allowed
* When `video_list` is present, `audio` is ignored
* `video_list` supports at most 1 video
* `multi_prompt` supports up to 6 shots, with `index` starting from 1 and increasing continuously
## Image Reference Syntax
The Omni model uses `<<>>` syntax to reference images in prompts, providing a unified text-to-video/image-to-video experience:
| Syntax | Description |
| --------------- | -------------------------------------------------- |
| `<<>>` | References the 1st image in the `image_urls` array |
| `<<>>` | References the 2nd image in the `image_urls` array |
**Auto Reference**: If `image_urls` is provided but the prompt does not contain any `<<>>` reference, the system will automatically prepend `<<>>` to the prompt.
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video (Standard Mode)
```json theme={null}
{
"model": "kling-v3-omni",
"prompt": "A golden retriever running on the beach, sunset, cinematic",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
```
### Case 2: Image Reference (Single Image)
```json theme={null}
{
"model": "kling-v3-omni",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "pro",
"duration": 5
}
```
### Case 3: Multiple Image References
```json theme={null}
{
"model": "kling-v3-omni",
"prompt": "The character in <<>> walks toward the scene in <<>>",
"image_urls": [
"https://example.com/character.jpg",
"https://example.com/scene.jpg"
],
"mode": "pro",
"duration": 5
}
```
### Case 4: Image Provided Without Explicit Reference (Auto-added)
```json theme={null}
{
"model": "kling-v3-omni",
"prompt": "The person slowly turns and smiles",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "std",
"duration": 5
}
```
> The system will automatically prepend `<<>>` to the prompt, equivalent to `"<<>>The person slowly turns and smiles"`.
### Case 5: Generate Video with Audio
```json theme={null}
{
"model": "kling-v3-omni",
"prompt": "A yellow canary singing on a branch",
"audio": true,
"mode": "std",
"duration": 5
}
```
> **Note**: `audio` is mutually exclusive with `video_list`. When `video_list` has a value, the `audio` parameter is not needed.
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Kling v3 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/kling-v3/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns task ID for subsequent queries
- Supports text-to-video, image-to-video (first frame/first-last frame control)
- Supports standard mode (720P), professional mode (1080P), and 4K mode
- Supports video durations from 3 to 15 seconds
- Supports generating videos with audio
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-v3",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "kling-v3",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "kling-v3",
prompt: "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
mode: "std",
duration: 5,
aspect_ratio: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "kling-v3",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "kling-v3",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"kling-v3",
"prompt" => "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode" => "std",
"duration" => 5,
"aspect_ratio" => "16:9"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "kling-v3",
prompt: "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
mode: "std",
duration: 5,
aspect_ratio: "16:9"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "kling-v3",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""kling-v3"",
""prompt"": ""A golden cat running on a sunlit meadow, slow motion, cinematic quality"",
""mode"": ""std"",
""duration"": 5,
""aspect_ratio"": ""16:9""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_xxxxxxxxxx"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `kling-v3` - Kling v3 (recommended)
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text prompt
Describe scenes, actions, styles in detail for better generation results. English prompts are recommended.
Example: `"a golden retriever running on the beach, sunset, cinematic"`
Negative prompt to exclude unwanted content
Example: `"blurry, low quality, distorted"`
Generation mode
Options:
* `std` - Standard mode (720P)
* `pro` - Professional mode (1080P)
* `4k` - 4K mode
Default: `std`
Default: `5`
Video duration (seconds)
Range: 3-15 (minimum 3 seconds, maximum 15 seconds)
**⚠️ Note:** Must be a plain number (e.g. `6`), do not add quotes, otherwise an error will occur
Video aspect ratio
Options:
* `16:9` - Landscape
* `9:16` - Portrait
* `1:1` - Square
Default: `16:9`
Image URL array for image-to-video generation
* Pass **1 image**: used as first frame
* Pass **2 images**: automatically assigned as first frame + last frame
Maximum 2 images supported
Example: `["https://example.com/first.jpg"]`
* Maximum 2 images supported
* Image URLs must be publicly accessible without hotlink protection
* In image-to-video mode, `aspect_ratio` may be overridden by the actual image ratio
Whether to add watermark
Whether to generate video with audio
Whether to enable multi-shot mode.
* `true`
* `false`
Shot split method: `customize` / `intelligence`.
Required when `multi_shot=true`.
Per-shot information, such as prompt and duration.
Define shot order, prompt, and duration via `index`, `prompt`, and `duration`.
* Supports 1 to 6 shots
* Maximum content length per shot is 512
* Each shot duration must be >= 1 and cannot exceed total task duration
* Sum of all shot durations must equal top-level `duration`
Format:
```json theme={null}
"multi_prompt": [
{ "index": 1, "prompt": "string", "duration": 5 },
{ "index": 2, "prompt": "string", "duration": 5 }
]
```
Required when `multi_shot=true` and `shot_type=customize`.
Reference subject list, up to 3 subjects.
* Create on the fly via `name`, `description`, `element_input_urls`
Example:
```json theme={null}
[
{
"name": "element_dog",
"description": "a golden retriever, fluffy fur, friendly expression",
"element_input_urls": [
"https://example.com/image1.png",
"https://example.com/image2.png"
]
},
{
"name": "element_cat",
"description": "an orange tabby cat, round face, bright eyes",
"element_input_urls": [
"https://example.com/image1.png",
"https://example.com/image2.png"
]
}
]
```
Notes:
* `name`, `description`, and `element_input_urls` are required for on-the-fly creation
* `element_input_urls`: 2-4 images per subject (first as frontal image, rest as references)
* Reference elements in `prompt` with `@name`, e.g. `"@element_dog chasing @element_cat on grass"`
### Parameter Constraints
* `mode=4k` is supported for `kling-v3`
* `image_urls` supports up to 2 images (1 first frame, 2 first+last frames)
* Last-frame-only input is invalid (must include first frame)
* When `multi_shot=true`, top-level `prompt` can be omitted
* `multi_prompt` supports up to 6 shots, and `index` must start from 1 and be continuous
## Feature Support Matrix
| Type | Feature | std 5s | std 10s | std 15s | pro 5s | pro 10s |
| -------------- | ----------- | ------ | ------- | ------- | ------ | ------- |
| Text-to-Video | Generation | ✅ | ✅ | ✅ | ✅ | ✅ |
| Image-to-Video | Generation | ✅ | ✅ | ✅ | ✅ | ✅ |
| Image-to-Video | First Frame | ✅ | ✅ | ✅ | ✅ | ✅ |
| Image-to-Video | Last Frame | ✅ | ✅ | ✅ | ✅ | ✅ |
## Text-to-Video vs Image-to-Video
The system automatically determines the mode based on whether `image_urls` is provided: no images means text-to-video, with images means image-to-video.
| Parameter | Text-to-Video | Image-to-Video |
| ----------------- | ----------------- | ----------------------------------- |
| `prompt` | ✅ Required | ✅ Required |
| `image_urls` | ❌ Not used | ✅ Required (1-2 images) |
| `negative_prompt` | ✅ Optional | ✅ Optional |
| `mode` | ✅ Optional | ✅ Optional |
| `duration` | ✅ Optional (3-15) | ✅ Optional (3-15) |
| `aspect_ratio` | ✅ Optional | ⚠️ May be overridden by image ratio |
| `watermark` | ✅ Optional | ✅ Optional |
| `audio` | ✅ Optional | ✅ Optional |
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video (Standard Mode)
```json theme={null}
{
"model": "kling-v3",
"prompt": "A golden cat running on a sunlit meadow, slow motion, cinematic quality",
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
```
### Case 2: Text-to-Video (Pro Mode + Negative Prompt)
```json theme={null}
{
"model": "kling-v3",
"prompt": "Tokyo Shibuya crossing at night, neon lights reflected on wet ground, people walking with umbrellas",
"negative_prompt": "blurry, low quality, distorted",
"mode": "pro",
"duration": 10,
"aspect_ratio": "16:9"
}
```
### Case 3: Text-to-Video (15 seconds)
```json theme={null}
{
"model": "kling-v3",
"prompt": "a time-lapse of a flower blooming in a garden",
"duration": 15,
"aspect_ratio": "16:9"
}
```
### Case 4: Image-to-Video (First Frame)
```json theme={null}
{
"model": "kling-v3",
"prompt": "the cat slowly walks forward and looks around",
"image_urls": ["https://example.com/cat.jpg"],
"mode": "std",
"duration": 5
}
```
### Case 5: Image-to-Video (First + Last Frame Control)
```json theme={null}
{
"model": "kling-v3",
"prompt": "smooth cinematic transition",
"image_urls": [
"https://example.com/frame-start.jpg",
"https://example.com/frame-end.jpg"
],
"mode": "std",
"duration": 5
}
```
### Case 6: Generate Video with Audio
```json theme={null}
{
"model": "kling-v3",
"prompt": "A rock singer singing on this stage, concert scene, flashing lights",
"audio": true,
"mode": "std",
"duration": 5
}
```
### Case 7: Multi-Shot Storyboard (`customize`, 15 seconds, portrait with audio)
```json theme={null}
{
"model": "kling-v3",
"multi_prompt": [
{
"index": 1,
"prompt": "Two friends talking under a streetlight at night. Warm glow, casual poses, no dialogue.",
"duration": 2
},
{
"index": 2,
"prompt": "A runner sprinting through a forest, leaves flying. Low-angle shot, focus on movement.",
"duration": 3
},
{
"index": 3,
"prompt": "A woman hugging a cat, smiling. Soft sunlight, cozy home setting, emphasize warmth.",
"duration": 3
},
{
"index": 4,
"prompt": "A door creaking open, shadowy hallway. Dark tones, minimal details, eerie mood.",
"duration": 3
},
{
"index": 5,
"prompt": "A man slipping on a banana peel, shocked expression. Exaggerated pose, bright colors.",
"duration": 3
},
{
"index": 6,
"prompt": "A sunset over mountains, small figure walking away. Wide angle, peaceful atmosphere.",
"duration": 1
}
],
"multi_shot": true,
"shot_type": "customize",
"duration": 15,
"mode": "pro",
"audio": true,
"aspect_ratio": "9:16"
}
```
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Kling Video O1 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/kling-video-o1/generation
POST https://api.apimart.ai/v1/videos/generations
- Reasoning-enhanced model for highest quality video generation
- Async processing mode, returns task ID for subsequent queries
- Unified text-to-video/image-to-video interface with image reference syntax
- Supports standard mode (720P) and professional mode (1080P)
- Reference images in prompts using `<<>>` syntax
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-video-o1",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "kling-video-o1",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "kling-video-o1",
prompt: "Make the person in <<>> wave at the camera",
image_urls: ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
mode: "std",
duration: 5,
aspect_ratio: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "kling-video-o1",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": []string{"https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"},
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "kling-video-o1",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"kling-video-o1",
"prompt" => "Make the person in <<>> wave at the camera",
"image_urls" => ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode" => "std",
"duration" => 5,
"aspect_ratio" => "16:9"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "kling-video-o1",
prompt: "Make the person in <<>> wave at the camera",
image_urls: ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
mode: "std",
duration: 5,
aspect_ratio: "16:9"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "kling-video-o1",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "std",
"duration": 5,
"aspect_ratio": "16:9"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""kling-video-o1"",
""prompt"": ""Make the person in <<>> wave at the camera"",
""image_urls"": [""https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp""],
""mode"": ""std"",
""duration"": 5,
""aspect_ratio"": ""16:9""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_xxxxxxxxxx"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `kling-video-o1` - Kling Video O1 (reasoning-enhanced, highest quality)
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Positive text prompt
The prompt must not exceed 2,500 characters.
Supports referencing images from `image_urls` using `<<>>` syntax, where `N` starts from 1.
Example: `"Make the person in <<>> wave at the camera"`
If images are provided but the prompt does not contain any `<<>>` reference, the system will automatically prepend `<<>>` to the prompt.
Generation mode
Options:
* `std` - Standard mode (720P)
* `pro` - Professional mode (1080P)
Default: `std`
Video duration (seconds)
Options: `5` or `10`
Default: `5`
Video aspect ratio
Options:
* `16:9` - Landscape
* `9:16` - Portrait
* `1:1` - Square
Default: `16:9`
Image URL array for image referencing
Reference corresponding images in the prompt using `<<>>` syntax (N starts from 1)
Example: `["https://example.png"]`
* Image URLs must be publicly accessible without hotlink protection
* In image-to-video mode, `aspect_ratio` may be overridden by the actual image ratio
* Up to two images. The first item in the array is the start frame, and the second is the end frame
Role-based image array, recommended for image-to-video.
Each item format: `{ "url": "...", "role": "..." }`
* `first_frame`: first frame
* `last_frame`: last frame
* `reference`: reference image
- `image_urls` and `image_with_roles` are mutually exclusive, do not pass both.
- When more than 2 images are provided, setting start/end frames is not supported.
Reference video list (URL-based), up to 1 video.
Use `refer_type` to distinguish types:
* `base`: video to be edited (default)
* `feature`: feature reference video
Use `keep_original_sound` to control whether to keep original audio:
* `no`: do not keep (default)
* `yes`: keep original sound
Request format:
```json theme={null}
"video_list":[
{ "video_url": "video_url", "refer_type": "base", "keep_original_sound": "no" }
]
```
* `video_url` cannot be empty, and the video URL must be accessible
* When `refer_type=base`:
* Start/end frames cannot be defined
* Reference video must be 3-10 seconds
* Generated video duration follows the uploaded video
* When `refer_type=feature` and `video_url` is not empty:
* `image_urls` can only include a first-frame image
* Video requirements: MP4/MOV only; duration at least 3 seconds; resolution 720px-2160px; frame rate 24-60fps (output is 24fps); size no more than 200MB
## Image Reference Syntax
The Video O1 model uses `<<>>` syntax to reference images in prompts, providing a unified text-to-video/image-to-video experience:
| Syntax | Description |
| --------------- | -------------------------------------------------- |
| `<<>>` | References the 1st image in the `image_urls` array |
| `<<>>` | References the 2nd image in the `image_urls` array |
**Auto Reference**: If `image_urls` is provided but the prompt does not contain any `<<>>` reference, the system will automatically prepend `<<>>` to the prompt.
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video (Highest Quality)
```json theme={null}
{
"model": "kling-video-o1",
"prompt": "A cinematic shot of a city skyline at golden hour",
"mode": "pro",
"duration": 5,
"aspect_ratio": "16:9"
}
```
### Case 2: Image Reference (Single Image)
```json theme={null}
{
"model": "kling-video-o1",
"prompt": "Make the person in <<>> wave at the camera",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "pro",
"duration": 5
}
```
### Case 3: Multiple Image References
```json theme={null}
{
"model": "kling-video-o1",
"prompt": "The character in <<>> walks toward the scene in <<>>",
"image_urls": [
"https://example.com/character.jpg",
"https://example.com/scene.jpg"
],
"mode": "pro",
"duration": 5
}
```
### Case 4: Image Provided Without Explicit Reference (Auto-added)
```json theme={null}
{
"model": "kling-video-o1",
"prompt": "The person slowly turns and smiles",
"image_urls": ["https://upload.apimart.ai/f/models/9998230426123070-e9d6af04-cb5e-4731-8ae7-abf144cb0d29-9998230586368386-29641169-f698-4ab9-9b6d-380899e6521e-9998230593110693-c1741a3a-.webp"],
"mode": "std",
"duration": 5
}
```
> The system will automatically prepend `<<>>` to the prompt, equivalent to `"<<>>The person slowly turns and smiles"`.
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# MiniMax-H3 Context-IR Prompt Enhancement
Source: https://docs.apimart.ai/en/api-reference/videos/minimax-h3/context-ir
POST https://api.apimart.ai/v1/videos/generations
- Multimodal context understanding that produces an enhanced structured prompt (text only, no video)
- Shares the same media fields and mutual-exclusion rules as H3 video generation
- Token-based billing; typically completes in 20~40 seconds
- Use alone, or as step 1 of the 768P preview → 2K regeneration workflow
**Full 2K Workflow** (optional): ① Context-IR enhances the prompt → ② [MiniMax-H3](/en/api-reference/videos/minimax-h3/generation) with `768P` for a preview → ③ [Regeneration](/en/api-reference/videos/minimax-h3/regeneration) upscales to 2K. Combined unit prices match direct 2K, with cheaper retries. You can also call this endpoint alone.
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "MiniMax-H3-Context-IR",
"prompt": "Epic space-opera trailer: a female captain alone before a huge viewport as the last fleet gathers and jumps away.",
"duration": 5,
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "MiniMax-H3-Context-IR",
"prompt": "Epic space-opera trailer: a female captain alone before a huge viewport as the last fleet gathers and jumps away.",
"duration": 5,
"aspect_ratio": "16:9",
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "MiniMax-H3-Context-IR",
prompt: "Epic space-opera trailer: a female captain alone before a huge viewport as the last fleet gathers and jumps away.",
duration: 5,
aspect_ratio: "16:9",
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
## Authorization
Bearer Token auth. Get a key from the [API Key Management Page](https://apimart.ai/keys).
```
Authorization: Bearer YOUR_API_KEY
```
## Overview
Send your idea plus optional media for multimodal understanding; receive a **structured, richer prompt**.
* **No video is produced.** Result is in `result.prompt` (not `result.videos`)
* Media fields use the **same validation rules** as [video generation](/en/api-reference/videos/minimax-h3/generation) (frame vs reference mutual exclusion; audio cannot be alone) so the same inputs can go to generation next
Completed task query example:
```json theme={null}
{
"code": 200,
"data": {
"actual_time": 28,
"completed": 1700000128,
"cost": 0.011204,
"created": 1700000100,
"credits_cost": 0.11204,
"estimated_time": 100,
"id": "task_01J9HA7J*************",
"progress": 100,
"result": {
"prompt": "integrated_multimodal_description: [Shot 1] Cinematic, close-up shot. The camera slowly pushes in on a lone adult astronaut standing in a dimly lit, metallic corridor. The astronaut wears a weathered, white and silver extravehicular spacesuit heavily scuffed with grey dust, featuring a completely opaque, gold-tinted helmet visor. The astronaut slowly pushes open a rusted, thick steel airlock door on the right side of the frame. As the heavy metal door shifts, a sudden, intense beam of vibrant green light spills across the dark frame, illuminating the intricate fabric folds of the suit. The curved golden visor vividly reflects a dense, tangled mass of luminescent green leaves and vines. [Shot 2] At 00:02.500, the camera cuts to a wide shot from directly behind the astronaut from Shot 1, smoothly pedestaling up to reveal the interior of the abandoned orbital station. The vast, hexagonal titanium room is completely overrun by a lush, zero-gravity living garden. Giant, emerald-green vines spiral tightly around cracked, grey ceiling support beams, while thick patches of bioluminescent cyan moss emit a soft glow from the rusted floor grid. Several large, perfectly spherical water droplets float weightlessly in the midground, refracting the ambient green light. The astronaut lowers their heavy, white-gloved hands to their sides, standing perfectly motionless before the massive canopy of overgrown flora.\noverall_soundscape: A loud, grinding metallic creak dominates the foreground as the heavy steel door shifts, instantly followed by a pronounced, high-pitched hiss of escaping pressurized air. A continuous, low-frequency mechanical hum rumbles in the background, establishing the station's deadened room tone. As the space opens, the distinct, crisp rustle of thick foliage is clearly heard, accompanied by soft, resonant liquid plops as unseen water drops collide in the metallic chamber.\nnon_diegetic_music: Ambient electronic score, slow tempo, featuring a deep, sustained synthesizer drone heavily overlaid with delicate, shimmering glockenspiel notes and a solitary, reverberating cello."
},
"status": "completed",
"usage": {
"input_tokens": 5512,
"output_tokens": 2388,
"total_tokens": 7900
}
}
}
```
Pass `result.prompt` **as-is** to `MiniMax-H3` as `prompt`.
## Request Parameters
Fixed value: `MiniMax-H3-Context-IR`
Whether to run content moderation before submitting the Context-IR task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Original idea text, **≤ 7000 characters**
Target video duration (seconds), **4\~15**, default `5`. Affects pacing language in the enhanced prompt.
Target aspect ratio. **Required for text-only input**, and cannot be `adaptive`.
Common values: `16:9`, `9:16`, `1:1`, `4:3`, `3:4`, `21:9`, etc.
First-frame image URL
Last-frame image URL
Reference images (always treated as references), ≤ **9**
Role-tagged images: `first_frame` / `last_frame` / `reference_image`
Reference videos, ≤ **3**; each 2\~15s, total ≤ 15s
Reference audio, ≤ **3**; cannot be used alone — pair with image or video
## Billing
**Token-based** (only H3-family model billed by tokens):
| Item | Price |
| ------------- | -------------------- |
| Input tokens | **\$0.87 / million** |
| Output tokens | **\$3.45 / million** |
A typical call (\~5.6k input + \~3.4k output tokens) is about **\$0.0167**.
A fixed deposit is pre-charged on submit, then settled against real `prompt_tokens` / `completion_tokens` (refund excess / charge shortfall). Multimodal inputs significantly increase input tokens.
## Notes
1. Usually **20\~40 seconds**; poll [task status](/en/api-reference/tasks/status) every **3\~5 seconds**.
2. Bad params → sync **400** (no task, no charge); runtime failures go to `failed` with auto refund.
3. Full workflow notes are on the [Regeneration](/en/api-reference/videos/minimax-h3/regeneration) page.
## Response
Status code; 200 on success
On submit: `status` / `task_id`
Initially `submitted`
Task ID
# MiniMax-H3 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/minimax-h3/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns a task ID for subsequent queries
- Supports text-to-video, image-to-video (first / last / first+last frame), and multimodal reference-to-video (reference images + videos + audio)
- Supports 2K / 768P resolution, duration 4 ~ 15 seconds, with audio track
- Shares the same submit and query APIs as MiniMax-Hailuo-02 / MiniMax-Hailuo-2.3
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "MiniMax-H3",
"prompt": "A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work",
"duration": 5,
"resolution": "2K",
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "MiniMax-H3",
"prompt": "A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work",
"duration": 5,
"resolution": "2K",
"aspect_ratio": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "MiniMax-H3",
prompt: "A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work",
duration: 5,
resolution: "2K",
aspect_ratio: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "MiniMax-H3",
"prompt": "A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work",
"duration": 5,
"resolution": "2K",
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "MiniMax-H3",
"prompt": "A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work",
"duration": 5,
"resolution": "2K",
"aspect_ratio": "16:9"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"MiniMax-H3",
"prompt" => "A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work",
"duration" => 5,
"resolution" => "2K",
"aspect_ratio" => "16:9"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "MiniMax-H3",
prompt: "A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work",
duration: 5,
resolution: "2K",
aspect_ratio: "16:9"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "MiniMax-H3",
"prompt": "A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work",
"duration": 5,
"resolution": "2K",
"aspect_ratio": "16:9"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""MiniMax-H3"",
""prompt"": ""A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work"",
""duration"": 5,
""resolution"": ""2K"",
""aspect_ratio"": ""16:9""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Content safety review failed",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please retry later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Generation Modes
MiniMax-H3 routes to the matching mode from request fields automatically. **You do not need a `mode` field**:
| Mode | Trigger | Capability |
| ------------------------------ | ------------------------------------------------------------------------------------------------ | ------------------------------------------------- |
| **Text-to-Video (T2V)** | Only `prompt` and common fields | Pure text-driven generation |
| **Image-to-Video (I2V)** | `first_frame_image` / `last_frame_image` (or `first_frame` / `last_frame` in `image_with_roles`) | First frame, last frame, first+last frame control |
| **Multimodal Reference (R2V)** | `image_urls` / `video_urls` / `audio_urls`, or `reference_image` in `image_with_roles` | Reference images + videos + audio |
**Strict mutual exclusion**: Image-to-video fields (`first_frame_image` / `last_frame_image`, and `first_frame` / `last_frame` in `image_with_roles`) cannot be combined with multimodal reference fields (`image_urls`, `video_urls`, `audio_urls`, and `reference_image` in `image_with_roles`). Mixing them returns **400**.
**Audio alone is not allowed.** If you pass `audio_urls`, you must also provide at least one reference image or reference video.
## Request Parameters
### Common Fields
Fixed value: `MiniMax-H3`
**`model` is required and must be sent explicitly.** Clients already integrated with Hailuo can switch by setting `model` to `MiniMax-H3`.
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description. **Required and non-empty in every scenario**, max **7000** characters per request.
Describe scene, subject, motion, and style in detail for better results.
Example: `"A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work"`
Output duration (seconds)
* Range: integer from `4` to `15`
* Default: `5`
Video resolution
Options:
* `2K` (default)
* `768P`
Aspect ratio. You may also pass `size` or `ratio` with the same effect.
Allowed ratios: `21:9`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`
Behavior by scenario is described in “Aspect Ratio Rules” below.
Whether to add an AIGC watermark
Default: `false`
Compatible alias: `aigc_watermark`
URL that receives a push when the task reaches a terminal state (success / failure)
Use `webhook`. Do not pass the official `callback_url`. `callback_url` is reserved for internal use and is not accepted from users.
### Image-to-Video Fields
For **first / last frame** image-to-video, specify roles explicitly. Do not infer from `image_urls` count.
First-frame image URL
When provided, this image is used as the **starting frame** of the video.
Last-frame image URL
When provided, this image is used as the **ending frame**. Combine with `first_frame_image` for first+last frame control.
### Multimodal Reference Fields
Array of reference image URLs
**Every image in `image_urls` is treated as a reference image (`reference_image`)**, regardless of count. They are never auto-mapped to first / first+last frames by length.
* Count: ≤ **9**
Array of reference video URLs
* Count: ≤ **3**
* Format and limits: see “Input Media Limits” below
Array of reference audio URLs
* Count: ≤ **3**
* Cannot be used alone; must be paired with a reference image or reference video
### Shared Image Array (Optional Form)
Role-tagged image array. Can replace `first_frame_image` / `last_frame_image` / `image_urls`. Each element:
Image URL
Image role. Allowed values:
* `first_frame` (also accepts `first`) — first frame (I2V)
* `last_frame` (also accepts `last`) — last frame (I2V)
* `reference_image` (also accepts `reference`) — reference image (R2V)
Example (first + last frame):
```json theme={null}
{
"image_with_roles": [
{"url": "https://example.com/start.png", "role": "first_frame"},
{"url": "https://example.com/end.png", "role": "last_frame"}
]
}
```
Example (reference image):
```json theme={null}
{
"image_with_roles": [
{"url": "https://example.com/char.png", "role": "reference_image"}
]
}
```
## Aspect Ratio Rules
| Scenario | `aspect_ratio` behavior |
| --------------------------------------- | --------------------------------------------------------------------- |
| **Text-to-video** (prompt only) | Must be a concrete ratio; omit or `adaptive` **falls back to `16:9`** |
| **Image-to-video** (first / last frame) | Determined by input image; any value is ignored (always `adaptive`) |
| **Multimodal reference** | Optional, default `adaptive`; may also set an explicit ratio |
Allowed concrete ratios: `21:9`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`.
## Input Media Limits
Total request body size ≤ **64 MB**. Use public URLs for large files; **do not use Base64**.
### Images
| Item | Limit |
| ------------------ | ----------------------------------------------------- |
| Format | JPG / JPEG / PNG / WEBP / HEIC / HEIF |
| Per file | ≤ 30 MB |
| Width / height | 256 \~ 5760 px |
| Aspect ratio (w/h) | 0.4 \~ 2.5 |
| Count | First frame ≤ 1, last frame ≤ 1, reference images ≤ 9 |
### Video (multimodal reference only)
| Item | Limit |
| ------------------ | --------------------------------------------- |
| Format | MP4 (`.mp4`), MOV (`.mov`) |
| Codec | Video H.264/AVC, H.265/HEVC; audio AAC, MP3 |
| Per file | ≤ 50 MB |
| Count | ≤ 3 |
| Duration | Per clip 2 \~ 15 s; **total duration ≤ 15 s** |
| Size / ratio / FPS | 256 \~ 5760 px / 0.4 \~ 2.5 / 23.976 \~ 60 |
### Audio (multimodal reference only)
| Item | Limit |
| -------- | ----------------------------------------- |
| Format | WAV, MP3 |
| Per file | ≤ 15 MB |
| Count | ≤ 3 |
| Duration | Per clip 2 \~ 15 s; total duration ≤ 15 s |
## Parameter Constraints
Violations are rejected with **400** (sensitive content may return **422**) and **are not billed**:
| Parameter | Constraint |
| ------------------------------------ | ------------------------------------------------------------------------------------- |
| `prompt` | Required and non-empty in every scenario, ≤ 7000 characters |
| `duration` | Integer from `4` to `15` only |
| `resolution` | `2K` (default) or `768P` |
| `aspect_ratio` | See “Aspect Ratio Rules”; T2V falls back to `16:9` when omitted |
| First/last frame vs reference assets | **Mutually exclusive**, cannot be mixed |
| `audio_urls` | Cannot be used alone; must pair with reference image or video |
| Reference images | ≤ 9 |
| Reference videos | ≤ 3 |
| Reference audio | ≤ 3 |
| Reference video probe failure | Returns `input_video_probe_failed` (URL unreachable or corrupt file), **not charged** |
## Response
Response status code, 200 on success
Response data array
Task status; `submitted` on initial submit
Unique task ID for querying status and results
## Request Examples
### Case 1: Text-to-Video
```json theme={null}
{
"model": "MiniMax-H3",
"prompt": "A boy playing basketball by the sea at dusk, waves crashing, cinematic camera work",
"duration": 6,
"resolution": "2K",
"aspect_ratio": "16:9"
}
```
### Case 2: Image-to-Video — First Frame
```json theme={null}
{
"model": "MiniMax-H3",
"prompt": "Pull focus to the people in the background and add more steam to the ramen bowl.",
"first_frame_image": "https://cdn.example.com/ramen.png",
"duration": 5,
"resolution": "2K"
}
```
### Case 3: Image-to-Video — First + Last Frame
```json theme={null}
{
"model": "MiniMax-H3",
"prompt": "Camera slowly transitions from morning light to sunset",
"first_frame_image": "https://cdn.example.com/morning.png",
"last_frame_image": "https://cdn.example.com/sunset.png",
"duration": 8
}
```
### Case 4: Multimodal Reference-to-Video
```json theme={null}
{
"model": "MiniMax-H3",
"prompt": "Character speaks: Follow the wind, live free. Leave worries behind, enjoy the moment. Voice references audio 1",
"image_with_roles": [
{"url": "https://cdn.example.com/char.png", "role": "reference_image"}
],
"video_urls": ["https://cdn.example.com/ref_motion.mp4"],
"audio_urls": ["https://cdn.example.com/ref_voice.mp3"],
"duration": 5,
"resolution": "2K"
}
```
### Case 5: First + Last Frame via image\_with\_roles
```json theme={null}
{
"model": "MiniMax-H3",
"prompt": "Camera slowly transitions from morning light to sunset",
"image_with_roles": [
{"url": "https://cdn.example.com/morning.png", "role": "first_frame"},
{"url": "https://cdn.example.com/sunset.png", "role": "last_frame"}
],
"duration": 8
}
```
**Query Task Results**
Video generation is asynchronous and returns a `task_id` on submit. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to poll progress and results.
Recommended poll interval: every **5 \~ 10 seconds**. Client timeout: **15 minutes**. On success, `result.videos[0].url` is the mp4 URL. Video URLs expire in about **24 hours** — save them promptly. Failed tasks are automatically refunded.
# MiniMax-H3-Max Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/minimax-h3/max
POST https://api.apimart.ai/v1/videos/generations
- MiniMax Video Generation V2 fast model with asynchronous task submission
- Supports text-to-video and image-to-video with first, last, or first-and-last frames
- Supports 768P / 480P, durations from 5 to 15 seconds, with audio
- Does not support 2K, middle frames, or multimodal reference generation
**Model selection:** Use `MiniMax-H3-Max` when speed matters and you only need text-to-video or first/last-frame control. For 2K, middle frames, reference images, reference videos, or reference audio, use [MiniMax-H3](/en/api-reference/videos/minimax-h3/generation).
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "MiniMax-H3-Max",
"prompt": "A detective in a trench coat turns around on a neon-lit street in the rain. The camera slowly pushes in as reflections shimmer on the pavement.",
"duration": 5,
"resolution": "768P",
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
response = requests.post(
"https://api.apimart.ai/v1/videos/generations",
headers={
"Authorization": "Bearer ",
"Content-Type": "application/json",
},
json={
"model": "MiniMax-H3-Max",
"prompt": "A detective turns around on a neon-lit street in the rain.",
"duration": 5,
"resolution": "768P",
"aspect_ratio": "16:9",
},
)
print(response.json())
```
```javascript JavaScript theme={null}
const response = await fetch("https://api.apimart.ai/v1/videos/generations", {
method: "POST",
headers: {
Authorization: "Bearer ",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "MiniMax-H3-Max",
prompt: "A detective turns around on a neon-lit street in the rain.",
duration: 5,
resolution: "768P",
aspect_ratio: "16:9",
}),
});
console.log(await response.json());
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Check your API key.",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance",
"type": "payment_required"
}
}
```
## Authentication
All endpoints require Bearer Token authentication. Get your key from the [API Key page](https://apimart.ai/keys).
```
Authorization: Bearer YOUR_API_KEY
```
## Choose the right model
| Capability | `MiniMax-H3` | `MiniMax-H3-Max` |
| --------------------- | --------------------------- | ------------------------------- |
| Resolution | `2K` / `768P`; default `2K` | `768P` / `480P`; default `768P` |
| Duration | 4–15 seconds | 5–15 seconds |
| Text-to-video | Supported | Supported |
| First / last frames | Supported | Supported |
| Middle frames | Supported | Not supported |
| Multimodal references | Images, video, and audio | Not supported |
| Input image charge | First 5 images are free | Free |
`MiniMax-H3-Max` does not support 2K and its output cannot be used as the source for [Regeneration](/en/api-reference/videos/minimax-h3/regeneration). Use `MiniMax-H3` when you need either capability.
## Generation modes
The request fields determine the mode automatically; do not send a `mode` field.
| Mode | Trigger | Behavior |
| -------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------- |
| Text-to-video (T2V) | Only `prompt` and common fields | Generates from text |
| Image-to-video (I2V) | `first_frame_image` / `last_frame_image`, or equivalent roles in `image_with_roles` | Controls the first frame, last frame, or both |
This model does not support `image_urls`, `video_urls`, `audio_urls`, or `image_with_roles[].role = "reference_image"`. Any reference-media field returns HTTP 400 synchronously; no task is created or charged.
## Request parameters
Fixed value: `MiniMax-H3-Max`
Model IDs are case-insensitive; `minimax-h3-max` is also accepted.
A non-empty description of the video. Required in every mode.
Maximum: `7000` characters.
Video duration in seconds.
* Integer from `5` to `15`
* Default: `5`
* 4 seconds is not supported
Output resolution:
* `768P` (default)
* `480P`
`2K`, `1440P`, and `2048P` are not supported. Invalid values return HTTP 400 and are not silently downgraded.
Output aspect ratio. The aliases `size` and `ratio` are also accepted.
Text-to-video values: `21:9`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`.
* T2V without this field, or with `adaptive`: falls back to `16:9`
* I2V: determined by the input image; this field is ignored
Public image URL used as the video's first frame.
Public image URL used as the video's last frame. It can be used alone or together with `first_frame_image`.
Role-based image array that can replace `first_frame_image` and `last_frame_image`.
Public image URL
Supported roles:
* `first_frame`; aliases include `first` and `start`
* `last_frame`; aliases include `last`, `end_frame`, and `tail`
Each role accepts at most one image. `role` cannot be empty.
Whether to add an AIGC watermark. Alias: `aigc_watermark`.
Receives a notification when the task reaches a successful or failed terminal state.
Use `webhook`, not MiniMax's `callback_url`. The gateway reserves `callback_url` for internal polling acceleration.
## Unsupported parameters
The following values return HTTP 400 before task creation and billing:
| Parameter / value | Reason |
| --------------------------------------------- | -------------------------------------------------------------- |
| `image_urls` | Treated as reference images, which this model does not support |
| `image_with_roles[].role = "reference_image"` | Only first and last frames are supported |
| `video_urls` / `video_url` | Reference video is not supported |
| `audio_urls` / `audio_url` | Reference audio is not supported |
| `resolution: "2K"` | Only `768P` and `480P` are supported |
| `duration: 4` or a value above `15` | Only 5–15 seconds are supported |
For reference media, 2K, middle frames, or a 4-second video, change `model` to `MiniMax-H3` and follow the [MiniMax-H3 guide](/en/api-reference/videos/minimax-h3/generation).
## Image limits
The total request body must be 64 MB or less. Use public URLs; Base64 is not supported.
| Item | Limit |
| ----------------------------- | ---------------------------------------------------- |
| Formats | JPG / JPEG / PNG / WEBP / HEIC / HEIF |
| Per file | ≤ 30 MB |
| Width and height | 256–5760 px |
| Aspect ratio (width / height) | 0.4–2.5 |
| Count | Up to 1 first frame and 1 last frame; 2 images total |
Invalid images may fail during generation; failed tasks are refunded automatically.
## Examples
### First-frame image-to-video
```json theme={null}
{
"model": "MiniMax-H3-Max",
"prompt": "The camera slowly pushes in as steam rises and people move in the background.",
"first_frame_image": "https://cdn.example.com/ramen.png",
"duration": 5,
"resolution": "480P"
}
```
### First-and-last-frame image-to-video
```json theme={null}
{
"model": "MiniMax-H3-Max",
"prompt": "The scene gradually transitions from morning to sunset.",
"first_frame_image": "https://cdn.example.com/morning.png",
"last_frame_image": "https://cdn.example.com/sunset.png",
"duration": 8,
"resolution": "768P"
}
```
## Query a task
Submission returns a `task_id`. Poll [Task Status](/en/api-reference/tasks/status) every 5–10 seconds; use a client timeout of 15 minutes.
```bash theme={null}
curl https://api.apimart.ai/v1/tasks/task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ \
--header 'Authorization: Bearer '
```
| `status` | Meaning |
| ------------ | --------------------------------------------------------- |
| `pending` | Submitted or queued |
| `processing` | Generating |
| `completed` | Video URL is in `result.videos[0].url` |
| `failed` | Check `error.message`; the task is refunded automatically |
Generated video URLs typically expire after about 24 hours. Download and store the result promptly.
## Pricing
Total cost equals the per-second rate multiplied by video duration. First and last frame images are free.
| Item | Rate |
| ------------ | --------------------- |
| 768P video | **\$0.075 / second** |
| 480P video | **\$0.0495 / second** |
| Input images | **Free** |
The estimated amount is reserved at submission. Failed tasks receive a full automatic refund; the task response's `cost` field is authoritative.
## Errors
| Scenario | Result |
| ------------------------------------- | ----------------------- |
| Empty or over-7000-character `prompt` | 400; no task |
| `duration` outside 5–15 | 400; no task |
| Unsupported `resolution` | 400; no task |
| Any reference media | 400; no task |
| Invalid or duplicate image role | 400; no task |
| Insufficient balance | 402 |
| Content safety rejection | 422 |
| Rate limit | 429; retry with backoff |
Generation failures return `status = failed` with details in `error.message` and are refunded automatically.
## Response
Response status code; 200 on success
Submission result containing the initial task status and task ID
Initially `submitted`
Unique task identifier used to query progress and results
# MiniMax-H3 Regeneration
Source: https://docs.apimart.ai/en/api-reference/videos/minimax-h3/regeneration
POST https://api.apimart.ai/v1/videos/generations
- Regenerate MiniMax-H3 768P video into 2K
- Prefer source_task_id only; the platform auto-fills prompt, media, and source video
- Not generic upscaling: source must be an H3 768P output
- Per-second billing ($0.045/s output + same rate for reference videos)
**Full 2K Workflow** (optional): ① [Context-IR](/en/api-reference/videos/minimax-h3/context-ir) → ② [MiniMax-H3](/en/api-reference/videos/minimax-h3/generation) with `resolution: "768P"` → ③ this endpoint to 2K.\
`768P unit price + regeneration unit price = direct 2K unit price`, with cheaper iteration.
**Not a generic upscaler.** The source must be a **768P video produced by MiniMax-H3**. External videos (phone clips, other models, downloads) will be rejected.
## Recommended: `source_task_id` only
Pass only the `task_id` of a **successful MiniMax-H3 · 768P** job. The server fills in the rest.
```json theme={null}
{
"model": "MiniMax-H3-Regeneration",
"source_task_id": "task_01J9HA7J*************"
}
```
`source_task_id` must satisfy all of the following, or you get a **sync 400** (no task, no charge):
| Rule | Notes |
| --------------------- | ---------------------------------- |
| Owned by your account | Cannot upgrade another user’s task |
| Model is `MiniMax-H3` | Not other models |
| Status is successful | Task is `completed` |
| Resolution is `768P` | Must be a 768P preview output |
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "MiniMax-H3-Regeneration",
"source_task_id": "task_01J9HA7J*************"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "MiniMax-H3-Regeneration",
"source_task_id": "task_01J9HA7J*************",
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "MiniMax-H3-Regeneration",
source_task_id: "task_01J9HA7J*************",
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
## Authorization
Bearer Token auth. Get a key from the [API Key Management Page](https://apimart.ai/keys).
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Fixed value: `MiniMax-H3-Regeneration`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
ID of a **successful MiniMax-H3 · 768P** task on this platform.
When set, you do **not** need `prompt`, source video, or reference media — the server fills them.
## Source Video Specs
The source must match MiniMax-H3 768P output:
| Item | Requirement |
| -------------- | ---------------------------------------------- |
| Audio track | **Required**; silent video not supported |
| Frame rate | 24 fps |
| Width / height | Each divisible by 32 |
| Area | ≤ 768 × 1344 (1,032,192 pixels) |
| Frame count | 107\~362 frames, steps of 17 (~~4~~15 seconds) |
Spec failures fail the task with a reason and refund.
## Billing
Per second (same structure as H3 generation, different unit prices):
| Item | Price |
| --------------------- | --------------------------------------- |
| Output (768P → 2K) | **\$0.045 / s** |
| Input reference video | **\$0.045 / s** |
| Input images | First 5 free, then **\$0.0225 / image** |
| Input audio | Free |
```
Total = 0.045 × (source duration + reference video duration) + 0.0225 × max(0, image_count - 5)
```
> Media from the original 768P job is **billed again** on regeneration — not output seconds only.
**Examples**
| Scenario | Cost |
| ----------------------------------- | ----------------------- |
| 5s source, no extra media | \$0.225 |
| 10s source + 2 images | \$0.45 (images ≤5 free) |
| 6s source + 8s ref video + 7 images | \$0.675 |
With `source_task_id`, pre-charge uses the original task’s real output seconds.
## Request Examples
### source\_task\_id
```json theme={null}
{
"model": "MiniMax-H3-Regeneration",
"source_task_id": "task_01J9HA7J*************"
}
```
## Common Errors
Submit-time parameter errors are sync **400** (no task, no charge):
| Case | Notes |
| ------------------------ | ------------------------------------------------------ |
| Invalid `source_task_id` | Not yours / not MiniMax-H3 / not successful / not 768P |
Failed tasks are auto-refunded.
## Response
Status code; 200 on success
On submit: `status` / `task_id`; when complete, result is in `result.videos` (same as normal video jobs)
Initially `submitted`
Task ID for [status queries](/en/api-reference/tasks/status)
Poll [Get Task Status](/en/api-reference/tasks/status). On success use `result.videos[0].url`.
# MiniMax-Hailuo-2.3 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/minimax-hailuo-2.3/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns task ID for subsequent queries
- Supports text-to-video, image-to-video (first frame image)
- Supports 6s and 10s duration, 768p/1080p resolution
- Supports 15 camera movement commands, prompt auto-optimization, and watermark control
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "MiniMax-Hailuo-2.3",
"prompt": "A cute kitten running on the grass",
"duration": 6,
"resolution": "768p",
"prompt_optimizer": true,
"fast_pretreatment": false,
"watermark": false
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "MiniMax-Hailuo-2.3",
"prompt": "A cute kitten running on the grass",
"duration": 6,
"resolution": "768p",
"prompt_optimizer": True,
"fast_pretreatment": False,
"watermark": False
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "MiniMax-Hailuo-2.3",
prompt: "A cute kitten running on the grass",
duration: 6,
resolution: "768p",
prompt_optimizer: true,
fast_pretreatment: false,
watermark: false
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "MiniMax-Hailuo-2.3",
"prompt": "A cute kitten running on the grass",
"duration": 6,
"resolution": "768p",
"prompt_optimizer": true,
"fast_pretreatment": false,
"watermark": false,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "MiniMax-Hailuo-2.3",
"prompt": "A cute kitten running on the grass",
"duration": 6,
"resolution": "768p",
"prompt_optimizer": true,
"fast_pretreatment": false,
"watermark": false
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"MiniMax-Hailuo-2.3",
"prompt" => "A cute kitten running on the grass",
"duration" => 6,
"resolution" => "768p",
"prompt_optimizer" => true,
"fast_pretreatment" => false,
"watermark" => false
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "MiniMax-Hailuo-2.3",
prompt: "A cute kitten running on the grass",
duration: 6,
resolution: "768p",
prompt_optimizer: true,
fast_pretreatment: false,
watermark: false
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "MiniMax-Hailuo-2.3",
"prompt": "A cute kitten running on the grass",
"duration": 6,
"resolution": "768p",
"prompt_optimizer": true,
"fast_pretreatment": false,
"watermark": false
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""MiniMax-Hailuo-2.3"",
""prompt"": ""A cute kitten running on the grass"",
""duration"": 6,
""resolution"": ""768p"",
""prompt_optimizer"": true,
""fast_pretreatment"": false,
""watermark"": false
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Supported models:
* `MiniMax-Hailuo-2.3` - Hailuo 2.3
* `MiniMax-Hailuo-2.3-Fast` - Hailuo 2.3 Fast (lower latency)
**MiniMax-Hailuo-2.3-Fast**:
With this model, `first_frame_image` is required.
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description (max 2000 characters)
Describe scenes, actions, styles in detail for better generation results. Supports camera movement commands (see Camera Movement Commands below).
Example: `"A cute kitten running on the grass"`
Video duration (seconds)
Options:
* `6` - 6-second video
* `10` - 10-second video
Default: `6`
**1080p Limitation**: When using 1080p resolution, only 6-second duration is supported
Video resolution
Options:
* `768p` - High definition
* `1080p` - Full HD (only supports 6-second duration)
Default: `768p`
First frame image for the video
Supports two formats:
* **Public URL**: `https://example.com/start.jpg`
* **Base64 encoded**: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg...`
When provided, this image will be used as the starting frame of the video
**MiniMax-Hailuo-2.3-Fast**:
With this model, `first_frame_image` is required.
Whether to auto-optimize the prompt
When enabled, the system will automatically optimize your prompt for better generation results
Default: `true`
Whether to shorten prompt optimization time
When enabled, processing speed is faster but optimization quality may be slightly affected
Default: `false`
Whether to add watermark
Default: `false`
## Resolution and Duration Combinations
| Resolution | Supported Duration | Notes |
| ---------- | ------------------ | ----------------- |
| 768p | 6s, 10s | All supported |
| 1080p | 6s | 10s not supported |
## Camera Movement Commands
Use `[command]` syntax in the `prompt` to control camera movements. The command labels must be entered exactly as the Chinese labels shown below. 15 commands are supported:
| Category | Commands |
| ----------------- | ---------------------------------------------- |
| Pan | `[左移]` (pan left) `[右移]` (pan right) |
| Horizontal Rotate | `[左摇]` (rotate left) `[右摇]` (rotate right) |
| Push/Pull | `[推进]` (push in) `[拉远]` (pull out) |
| Vertical Move | `[上升]` (rise) `[下降]` (descend) |
| Vertical Rotate | `[上摇]` (tilt up) `[下摇]` (tilt down) |
| Zoom | `[变焦推近]` (zoom in) `[变焦拉远]` (zoom out) |
| Other | `[晃动]` (shake) `[跟随]` (follow) `[固定]` (static) |
**Usage example**:
```json theme={null}
{
"model": "MiniMax-Hailuo-2.3",
"prompt": "[推进]A cat running in the garden, camera slowly pushing in for a close-up"
}
```
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Quick Text-to-Video
```json theme={null}
{
"model": "MiniMax-Hailuo-2.3",
"prompt": "A cute kitten running on the grass, sunny day"
}
```
### Case 2: High-Quality 1080p Video
```json theme={null}
{
"model": "MiniMax-Hailuo-2.3",
"prompt": "City nightscape, neon lights flickering, traffic flowing",
"duration": 6,
"resolution": "1080p",
"prompt_optimizer": true,
"watermark": false
}
```
### Case 3: Image-to-Video with First Frame
```json theme={null}
{
"model": "MiniMax-Hailuo-2.3",
"prompt": "Kitten running towards camera, smiling and blinking",
"first_frame_image": "https://example.com/cat.jpg",
"duration": 6,
"resolution": "1080p"
}
```
### Case 4: Camera Movement Commands
```json theme={null}
{
"model": "MiniMax-Hailuo-2.3",
"prompt": "[推进]A cat running in the garden, camera slowly pushing in for a close-up",
"duration": 6,
"resolution": "768p"
}
```
### Case 5: Fast Pretreatment Mode
```json theme={null}
{
"model": "MiniMax-Hailuo-2.3",
"prompt": "Waves crashing on the beach at sunset",
"duration": 10,
"resolution": "768p",
"prompt_optimizer": true,
"fast_pretreatment": true
}
```
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# MiniMax-Hailuo-02 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/minimax-hailuo/generation
POST https://api.apimart.ai/v1/videos/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Supports text-to-video, image-to-video (first frame/last frame)
- Supports 5 and 10 second durations, multiple resolutions available
- Supports automatic prompt optimization and watermark control
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "MiniMax-Hailuo-02",
"prompt": "A cute cat running on the grass",
"duration": 5,
"resolution": "768p",
"prompt_optimizer": true,
"fast_pretreatment": false,
"watermark": false
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "MiniMax-Hailuo-02",
"prompt": "A cute cat running on the grass",
"duration": 5,
"resolution": "768p",
"prompt_optimizer": True,
"fast_pretreatment": False,
"watermark": False
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "MiniMax-Hailuo-02",
prompt: "A cute cat running on the grass",
duration: 5,
resolution: "768p",
prompt_optimizer: true,
fast_pretreatment: false,
watermark: false
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "MiniMax-Hailuo-02",
"prompt": "A cute cat running on the grass",
"duration": 5,
"resolution": "768p",
"prompt_optimizer": true,
"fast_pretreatment": false,
"watermark": false,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "MiniMax-Hailuo-02",
"prompt": "A cute cat running on the grass",
"duration": 5,
"resolution": "768p",
"prompt_optimizer": true,
"fast_pretreatment": false,
"watermark": false
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"MiniMax-Hailuo-02",
"prompt" => "A cute cat running on the grass",
"duration" => 5,
"resolution" => "768p",
"prompt_optimizer" => true,
"fast_pretreatment" => false,
"watermark" => false
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "MiniMax-Hailuo-02",
prompt: "A cute cat running on the grass",
duration: 5,
resolution: "768p",
prompt_optimizer: true,
fast_pretreatment: false,
watermark: false
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "MiniMax-Hailuo-02",
"prompt": "A cute cat running on the grass",
"duration": 5,
"resolution": "768p",
"prompt_optimizer": true,
"fast_pretreatment": false,
"watermark": false
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""MiniMax-Hailuo-02"",
""prompt"": ""A cute cat running on the grass"",
""duration"": 5,
""resolution"": ""768p"",
""prompt_optimizer"": true,
""fast_pretreatment"": false,
""watermark"": false
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please recharge",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get API Key:
Visit [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Fixed value: `MiniMax-Hailuo-02`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description
Describe the scene, actions, style, etc. in detail for better generation results
Example: `"A cute cat running on the grass"`
Video duration (seconds)
Options:
* `5` - 5 second video
* `10` - 10 second video
Default: `5`
**1080p Limitation**: When using 1080p resolution, only 5 second duration is supported
Video resolution
Options:
* `512p` - Standard definition
* `768p` - High definition
* `1080p` - Full HD (only supports 5 second duration)
Default: `768p`
Whether to automatically optimize the prompt
When enabled, the system will automatically optimize your prompt for better generation results
Default: `true`
Whether to reduce prompt optimization time
Enabling this can speed up processing, but may slightly affect optimization quality
Default: `false`
Whether to add watermark
Default: `false`
Video first frame image
Supports two formats:
* **Public URL**: `https://example.com/start.jpg`
* **Base64 encoded**: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg...`
Used to specify the starting frame of the video
Video last frame image
Supports two formats:
* **Public URL**: `https://example.com/end.jpg`
* **Base64 encoded**: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg...`
Used to specify the ending frame of the video
## Parameter Limitations
| Limitation | Description |
| ---------------- | -------------------------------------------------------------------- |
| Duration | Only supports 5 or 10 seconds |
| 1080p Resolution | Only supports 5 second duration |
| Image Format | Supports public URL or Base64 encoded (`data:image/jpeg;base64,...`) |
## Resolution and Duration Combinations
| Resolution | Supported Duration | Notes |
| ---------- | ------------------ | ----------------- |
| 512p | 5s, 10s | All supported |
| 768p | 5s, 10s | All supported |
| 1080p | 5s | 10s not supported |
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` on initial submission
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Quick Text-to-Video Generation
```json theme={null}
{
"model": "MiniMax-Hailuo-02",
"prompt": "A cute cat running on the grass in bright sunshine"
}
```
### Case 2: Generate High-Quality 1080p Video
```json theme={null}
{
"model": "MiniMax-Hailuo-02",
"prompt": "City night scene, neon lights flashing, traffic flowing",
"duration": 5,
"resolution": "1080p",
"prompt_optimizer": true,
"watermark": false
}
```
### Case 3: Generate Video from First Frame Image
```json theme={null}
{
"model": "MiniMax-Hailuo-02",
"prompt": "Person slowly turning around with a smile",
"duration": 5,
"resolution": "768p",
"first_frame_image": "https://example.com/portrait.jpg"
}
```
### Case 4: Transition Video with First and Last Frame Control
```json theme={null}
{
"model": "MiniMax-Hailuo-02",
"prompt": "Scene gradually transitions from day to night, sky color changing",
"duration": 10,
"resolution": "768p",
"first_frame_image": "https://example.com/day.jpg",
"last_frame_image": "https://example.com/night.jpg",
"prompt_optimizer": true
}
```
### Case 5: Fast Preprocessing Mode
```json theme={null}
{
"model": "MiniMax-Hailuo-02",
"prompt": "Waves crashing on the beach at sunset",
"duration": 5,
"resolution": "768p",
"prompt_optimizer": true,
"fast_pretreatment": true
}
```
**Query Task Results**
Video generation is an asynchronous task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# gemini-omni-1.1-flash-ext Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/omni-flash-ext/generation
POST https://api.apimart.ai/v1/videos/generations
- gemini-omni-1.1-flash-ext unified video generation model
- Supports Text-to-Video, single-image Image-to-Video, reference video, and 3-reference-image fusion
- Supports 720p/1080p/4k resolution and 4/6/8/10 second duration
- Asynchronous task API. Submit a task first, then query the result by task ID
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "gemini-omni-1.1-flash-ext",
"prompt": "a girl is dancing happily in a sunny garden",
"duration": 10,
"resolution": "1080p",
"aspect_ratio": "9:16"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "gemini-omni-1.1-flash-ext",
"prompt": "a girl is dancing happily in a sunny garden",
"duration": 10,
"resolution": "1080p",
"aspect_ratio": "9:16"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "gemini-omni-1.1-flash-ext",
prompt: "a girl is dancing happily in a sunny garden",
duration: 10,
resolution: "1080p",
aspect_ratio: "9:16"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "gemini-omni-1.1-flash-ext",
"prompt": "a girl is dancing happily in a sunny garden",
"duration": 10,
"resolution": "1080p",
"aspect_ratio": "9:16",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KS1H7ZYSJWH1N779S2FSHTKA"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance. Please recharge and try again",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests. Please try again later",
"type": "rate_limit_error"
}
}
```
## Authentication
All requests require Bearer Token authentication.
Get an API key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API key.
Add the following header when making requests:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name. Must be `gemini-omni-1.1-flash-ext`.
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description. We recommend describing the scene, subject, action, environment, camera movement, visual style, and audio cues in detail.
Example: `"a girl is dancing happily in a sunny garden"`
Video duration in seconds.
Supported values: `4`, `6`, `8`, `10`.
Other values such as `5` or `7` will return an `invalid_duration` error.
Do not pass `duration` when uploading a reference video. `duration` and `video_urls` cannot be passed at the same time.
Video resolution. Values are case-insensitive.
Supported values:
* `360p`
* `720p`
* `1080p`
* `4k`
Other resolutions will return an `invalid_resolution` error.
Video aspect ratio. Use it to control landscape or portrait output.
Common values:
* `16:9` - landscape
* `9:16` - portrait
Default: `16:9`
Compatibility field. It has the same meaning as `aspect_ratio`. If both are provided, keep them consistent.
Generation type, used to specify how the images are used.
Options:
* `frame` - First-frame mode. `image_urls` can only contain 1 image, used as the first frame of the video.
* `reference` - Reference mode. `image_urls` can contain 1 or 3 images, used as reference images.
When `generation_type` is `frame`, `image_urls` only supports 1 image; passing any other count returns an `unsupported_image_count` error.
Reference image URL array. You can omit it, provide 1 image, or provide 3 images, depending on `generation_type`:
* Omitted or empty array: Text-to-Video
* 1 image: single-image Image-to-Video
* 3 images: reference image fusion (only supported when `generation_type` is `reference`)
Relationship with `generation_type`:
* `generation_type` is `frame`: only 1 image can be uploaded.
* `generation_type` is `reference`: 1 or 3 images can be uploaded.
Only publicly accessible image URLs are supported.
The first-frame plus last-frame mode with 2 images is not supported. Passing 2 images returns an `unsupported_image_count` error. 4 or more images have not been fully verified and are not recommended.
Reference video URL array. You can omit it or provide 1 reference video.
Only publicly accessible HTTP/HTTPS video URLs are supported. You can pass it together with `image_urls`: images are used as identity or composition references, while the video is used as motion reference.
`gemini-omni-1.1-flash-ext` supports only 0 or 1 reference video. Passing 2 or more videos returns an `unsupported_video_count` error.
Do not pass `duration` when passing `video_urls`. `video_urls` and `duration` cannot be passed at the same time.
## Response
Response status code. Successful requests return `200`.
Returned task array.
Initial task status. It is `submitted` after successful submission.
Unique task ID for querying task status and result.
## Query Task Result
Video generation is asynchronous. After submission, the API returns a `task_id`. Use the [Get task status](/en/api-reference/tasks/status) endpoint to query progress and results.
```bash cURL theme={null}
curl --request GET \
--url https://api.apimart.ai/v1/tasks/task_01KS1H7ZYSJWH1N779S2FSHTKA \
--header 'Authorization: Bearer '
```
We recommend waiting 5-10 seconds after submission before the first query, then polling every 5-10 seconds. A single task usually completes in about 3-5 minutes.
### Successful Result Example
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KS1H7ZYSJWH1N779S2FSHTKA",
"status": "completed",
"progress": 100,
"created": 1779246294,
"completed": 1779246534,
"actual_time": 240,
"estimated_time": 600,
"cost": 0.4,
"credits_cost": 4,
"result": {
"videos": [
{
"url": ["https://cdn.example.com/videos/abc.mp4"],
"expires_at": 1779332760
}
]
}
}
}
```
### Failed Result Example
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KS1H7ZYSJWH1N779S2FSHTKA",
"status": "failed",
"progress": 100,
"created": 1779246294,
"completed": 1779246534,
"actual_time": 240,
"estimated_time": 600,
"cost": 0,
"credits_cost": 0,
"error": {
"message": "invalid duration 7, must be one of 4/6/8/10",
"code": "task_failed"
}
}
}
```
## Use Cases
### Scenario 1: Text-to-Video
```json theme={null}
{
"model": "gemini-omni-1.1-flash-ext",
"prompt": "a beautiful sunset over the ocean with seagulls flying",
"duration": 6,
"resolution": "720p",
"aspect_ratio": "16:9"
}
```
### Scenario 2: Single-Image Video
```json theme={null}
{
"model": "gemini-omni-1.1-flash-ext",
"prompt": "make the character smile and slowly turn around, cinematic camera motion",
"duration": 6,
"resolution": "1080p",
"aspect_ratio": "9:16",
"image_urls": ["https://example.com/character.jpg"]
}
```
### Scenario 3: 3-Reference-Image Fusion
```json theme={null}
{
"model": "gemini-omni-1.1-flash-ext",
"prompt": "a creative scene combining these elements with smooth camera motion",
"duration": 10,
"resolution": "1080p",
"aspect_ratio": "9:16",
"image_urls": [
"https://example.com/scene.jpg",
"https://example.com/character.jpg",
"https://example.com/product.jpg"
]
}
```
### Scenario 4: 4K Short Video
```json theme={null}
{
"model": "gemini-omni-1.1-flash-ext",
"prompt": "close-up of a hummingbird hovering in front of a red flower",
"duration": 4,
"resolution": "4k",
"aspect_ratio": "16:9"
}
```
### Scenario 5: Reference Video Generation
```json theme={null}
{
"model": "gemini-omni-1.1-flash-ext",
"prompt": "the same scene but at night with neon lights",
"resolution": "720p",
"aspect_ratio": "16:9",
"video_urls": ["https://example.com/reference.mp4"]
}
```
## Error Codes
| HTTP | Error type | Meaning | Suggested action |
| ---- | ------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------- |
| 400 | `invalid_request_error` | `model` is not `gemini-omni-1.1-flash-ext`, `prompt` is empty, or the JSON format is invalid | Check the request body |
| 400 | `invalid_duration` | `duration` is not `4`, `6`, `8`, or `10` | Use a supported duration |
| 400 | `invalid_resolution` | `resolution` is not `720p`, `1080p`, or `4k` | Use a supported resolution |
| 400 | `unsupported_image_count` | The number of `image_urls` is unsupported, commonly caused by passing 2 images | Use 0, 1, or 3 images |
| 400 | `unsupported_video_count` | The number of `video_urls` is unsupported, commonly caused by passing 2 or more videos | Use 0 or 1 reference video |
| 401 | `authentication_error` | Invalid token | Check the Bearer Token |
| 402 | `payment_required` | Insufficient balance | Recharge and try again |
| 429 | `rate_limit_error` | Rate limit exceeded | Reduce concurrency or try again later |
When a task fails, the task status API returns the failure reason in `data.error`. Common causes include temporary upstream quota exhaustion, content moderation failure, or upstream timeout.
# Pixverse v6 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/pixverse-v6/generation
POST https://api.apimart.ai/v1/videos/generations
- Pixverse v6 unified video generation model
- Supports text-to-video, image-to-video, first/last frame transition, multi-reference fusion, and video extension
- Supports 360p/540p/720p/1080p resolutions with 1-15 seconds duration
- Asynchronous task API; query the result by task ID after submission
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "pixverse-v6",
"prompt": "A cinematic shot of a corgi running through a sunflower field at golden hour",
"size": "16:9",
"resolution": "540p",
"duration": 5
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "pixverse-v6",
"prompt": "A cinematic shot of a corgi running through a sunflower field at golden hour",
"size": "16:9",
"resolution": "540p",
"duration": 5
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "pixverse-v6",
prompt: "A cinematic shot of a corgi running through a sunflower field at golden hour",
size: "16:9",
resolution: "540p",
duration: 5
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JWXXXXXXXXXXXX"
}
]
}
```
```json 400 theme={null}
{
"error": {
"type": "invalid_request_error",
"message": "invalid duration 20, allowed range: 1-15 seconds"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "insufficient quota: balance=0, required=0.25",
"type": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
## Authentication
All endpoints require authentication using a Bearer Token.
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to obtain your API Key.
Add the following header in your request:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name. Fixed to `pixverse-v6`.
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description, up to 5000 characters. Required for all modes.
Video resolution tier; directly affects pricing.
* `360p`: SD
* `540p`: Standard (default)
* `720p`: HD
* `1080p`: Full HD
Other resolution values will return a parameter error.
Video duration in seconds, range `1-15`.
First/last frame transition mode only supports `5` or `8` seconds.
Video aspect ratio. Only effective in text-to-video and multi-reference fusion modes.
* `16:9`: Landscape widescreen (default)
* `4:3`: Landscape 4:3
* `1:1`: Square
* `3:4`: Portrait 3:4
* `9:16`: Portrait vertical
* `2:3`: Portrait 2:3
* `3:2`: Landscape 3:2
* `21:9`: Cinematic widescreen
Random seed, range `0-2147483647`. Same prompt and seed can reproduce similar results.
Negative prompt used to exclude unwanted content, up to 2048 characters.
Whether to generate an audio track.
* `true`: Generate audio (increases pricing)
* `false`: No audio (default)
Whether to add a watermark in the bottom-right corner of the video.
* `true`: Add watermark
* `false`: No watermark (default)
Motion mode.
* `normal`: Standard mode (`pixverse-v6` only supports this value)
`fast` only applies to legacy models and will be rejected by the upstream when used with `pixverse-v6`.
Whether to generate a multi-clip continuous video. Only supported in text-to-video and image-to-video modes.
* `true`: Generate multi-clip continuous video
* `false`: Single clip (default)
Input image URL array for image-to-video; only the first image is used.
Images must be publicly accessible HTTP/HTTPS URLs.
First frame image URL for transition mode. Must be provided together with `last_frame_image`.
Last frame image URL for transition mode. Must be provided together with `first_frame_image`.
Reference image URL array for multi-reference fusion mode; supports 1-7 images.
Providing this field triggers multi-reference fusion mode.
Source task ID for video extension. Providing this field triggers video extension mode.
The source task must belong to the current user, use model `pixverse-v6`, and have status `completed`.
## Generation Modes
The adapter automatically dispatches to the corresponding generation mode based on request fields. Matching is done in priority order; the first match wins.
| Mode | Trigger | Description |
| --------------------------- | -------------------------------------------------------- | -------------------------------------------------- |
| Text-to-video | No image or extension fields | Generate video based on `prompt` |
| Image-to-video | `image_urls` with one image | Use the first image as input |
| First/last frame transition | Both `first_frame_image` and `last_frame_image` provided | Generate a smooth transition between two frames |
| Multi-reference fusion | `img_references` array provided | Fuse 1-7 reference images into a video |
| Video extension | `extend_from_task_id` provided | Continue generation from a completed Pixverse task |
All image inputs only accept publicly accessible HTTP/HTTPS URLs. base64 and Data URI are not supported. If you only have local images, upload them to object storage first and pass the URL.
## Parameter Rules
| Constraint | Description |
| ---------------------- | ---------------------------------------------------------------------------------------------- |
| Duration | `1 ≤ duration ≤ 15` seconds; transition mode only supports `5` or `8` seconds |
| Resolution | Only `360p`, `540p`, `720p`, `1080p` are supported |
| Aspect ratio | `size` is only effective in text-to-video and multi-reference fusion modes |
| Prompt length | `prompt` up to 5000 chars, `negative_prompt` up to 2048 chars |
| Image-to-video | `image_urls` only uses the first image |
| Transition | `first_frame_image` and `last_frame_image` must be provided together |
| Motion mode | `pixverse-v6` only supports `normal` |
| Multi-reference fusion | `img_references` supports 1-7 images |
| Video extension | `extend_from_task_id` must point to a `completed` `pixverse-v6` task owned by the current user |
## Response
Response status code. `200` on success.
Returned task array.
Initial task status. `submitted` upon successful submission.
Unique task identifier used for querying status and results.
## Querying Task Results
Video generation is an asynchronous task. After submission, a `task_id` is returned. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query progress and results.
```bash cURL theme={null}
curl --request GET \
--url https://api.apimart.ai/v1/tasks/task_01JWXXXXXXXXXXXX \
--header 'Authorization: Bearer '
```
It is recommended to poll every 5 seconds until the status becomes `completed` or `failed`.
### Successful Result Example
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KSPX48B8V1M6C2ZN0D0T4BKB",
"status": "completed",
"progress": 100,
"cost": 0.2,
"credits_cost": 2,
"created": 1779958948,
"completed": 1779958999,
"estimated_time": 100,
"actual_time": 51,
"result": {
"videos": [
{
"url": ["https://upload.apimart.ai/f/video/xxxx.mp4"],
"expires_at": 1780045399
}
]
}
}
}
```
The video URL is at `data.result.videos[0].url[0]`. The `url` field is itself an array. Video links typically expire after 24 hours; download or transfer them in time.
### Failed Result Example
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KSPX48B8V1M6C2ZN0D0T4BKB",
"status": "failed",
"progress": 100,
"cost": 0,
"credits_cost": 0,
"created": 1779958948,
"completed": 1779958960,
"error": {
"code": "task_failed",
"message": "pixverse error 400063: moderation failed",
"type": "task_failed"
}
}
}
```
On failure, `cost` is typically `0`. Read the error reason from `data.error.message`.
## Use Cases
### Case 1: Text-to-video
```json theme={null}
{
"model": "pixverse-v6",
"prompt": "A neon-lit alley in Tokyo at night, light rain, anamorphic lens flare",
"size": "21:9",
"resolution": "720p",
"duration": 8,
"seed": 42,
"audio": true
}
```
### Case 2: Image-to-video
```json theme={null}
{
"model": "pixverse-v6",
"prompt": "Camera slowly zooms in, gentle wind moves the leaves",
"image_urls": ["https://example.com/first-frame.jpg"],
"resolution": "540p",
"duration": 5
}
```
### Case 3: First/Last Frame Transition
```json theme={null}
{
"model": "pixverse-v6",
"prompt": "transform smoothly from a puppy to a cat",
"first_frame_image": "https://example.com/puppy.jpg",
"last_frame_image": "https://example.com/cat.jpg",
"resolution": "540p",
"duration": 5,
"motion_mode": "normal"
}
```
### Case 4: Multi-Reference Fusion
```json theme={null}
{
"model": "pixverse-v6",
"prompt": "A girl wearing the outfit from image 2, holding the cat from image 3",
"img_references": [
"https://example.com/character.jpg",
"https://example.com/outfit.jpg",
"https://example.com/cat.jpg"
],
"size": "9:16",
"resolution": "720p",
"duration": 5
}
```
### Case 5: Video Extension
```json theme={null}
{
"model": "pixverse-v6",
"prompt": "the character now walks into a forest",
"extend_from_task_id": "task_01JWXXXXXXXXXXXX",
"resolution": "540p",
"duration": 5
}
```
# seedance-1-5-pro Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/seedance-1-5-pro/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns task ID for subsequent queries
- Supports text-to-video, image-to-video (first frame/last frame)
- Supports audio generation
- Supports landscape, portrait, and square aspect ratios
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "seedance-1-5-pro",
"prompt": "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p",
"audio": true
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "seedance-1-5-pro",
"prompt": "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p",
"audio": True
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "seedance-1-5-pro",
prompt: "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
duration: 5,
aspect_ratio: "16:9",
resolution: "720p",
audio: true
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "seedance-1-5-pro",
"prompt": "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p",
"audio": true,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "seedance-1-5-pro",
"prompt": "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p",
"audio": true
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"seedance-1-5-pro",
"prompt" => "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration" => 5,
"aspect_ratio" => "16:9",
"resolution" => "720p",
"audio" => true
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "seedance-1-5-pro",
prompt: "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
duration: 5,
aspect_ratio: "16:9",
resolution: "720p",
audio: true
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "seedance-1-5-pro",
"prompt": "A cute kitten playing in the sunlight, fluffy fur, bright eyes",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p",
"audio": true
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""seedance-1-5-pro"",
""prompt"": ""A cute kitten playing in the sunlight, fluffy fur, bright eyes"",
""duration"": 5,
""aspect_ratio"": ""16:9"",
""resolution"": ""720p"",
""audio"": true
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `seedance-1-5-pro` - 1.5 Pro version, supports audio generation and first/last frame
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description
Describe scenes, actions, styles in detail for better generation results
Example: `"Sunset at the beach, golden sunlight on the sea, waves gently hitting the sand"`
Video duration (seconds)
Supported range: `4` \~ `12` seconds
Default: `5`
Video aspect ratio
Options:
* `16:9` - Landscape
* `9:16` - Portrait
* `1:1` - Square
* `4:3` - Traditional ratio
* `3:4` - Vertical traditional ratio
* `21:9` - Ultra-wide
Default: `16:9`
Video resolution
Options:
* `480p` - Standard definition
* `720p` - High definition
* `1080p` - Full HD
Default: `720p`
Seed integer for controlling the randomness of generated content
Value range: Integer between `-1` and `2^32-1`
* With the same request, if the model receives different seed values (e.g., not specifying seed or setting seed to -1, which will use a random number), different results will be generated
* With the same request, if the model receives the same seed value, similar results will be generated, but not guaranteed to be identical
Whether to generate audio
When set to `true`, the video will include AI-generated accompanying audio
Default: `true`
Audio generation is only supported by the Seedance 2.0 series and Seedance 1.5 Pro
Whether to fix the camera
When set to `true`, the camera position remains fixed
Default: `false`
## Resolution and Aspect Ratio Combinations
| Resolution | Supported Aspect Ratios | Notes |
| ---------- | ------------------------------- | ------------- |
| 480p | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | All supported |
| 720p | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | All supported |
| 1080p | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | All supported |
Image URL array for image-to-video generation
Auto role assignment rules:
* 1 image = first frame
* 2 images = first frame + last frame
Example: `["https://example.com/first.png", "https://example.com/last.png"]`
* `image_urls` and `image_with_roles` cannot be used together
Image array with roles for more precise control
Image URL address
Image role
Options:
* `first_frame` - First frame image, as video starting frame (only one supported)
* `last_frame` - Last frame image, as video ending frame (only one supported)
Example:
```json theme={null}
[
{"url": "https://example.com/start.png", "role": "first_frame"},
{"url": "https://example.com/end.png", "role": "last_frame"}
]
```
* `image_urls` and `image_with_roles` cannot be used together
* First frame and last frame only support one each
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video with Audio
```json theme={null}
{
"model": "seedance-1-5-pro",
"prompt": "Sunset at the beach, golden sunlight on the sea, waves gently hitting the sand",
"audio": true
}
```
### Case 2: High-Quality Portrait Short Video
```json theme={null}
{
"model": "seedance-1-5-pro",
"prompt": "A girl spinning under cherry blossom trees, petals falling with the wind",
"duration": 5,
"aspect_ratio": "9:16",
"resolution": "720p",
"audio": true
}
```
### Case 3: First Frame to Dynamic Video
```json theme={null}
{
"model": "seedance-1-5-pro",
"prompt": "Animate the image with natural dynamic effects",
"image_urls": ["https://example.com/first.png"],
"duration": 5,
"audio": true
}
```
### Case 4: Transition Effect with First/Last Frame
```json theme={null}
{
"model": "seedance-1-5-pro",
"prompt": "Scene transitions from day to night, city lights gradually turning on",
"image_with_roles": [
{"url": "https://example.com/day.png", "role": "first_frame"},
{"url": "https://example.com/night.png", "role": "last_frame"}
],
"duration": 5
}
```
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
## Differences from 1.0 Version
| Feature | 1.0 fast/quality | 1.5 Pro |
| --------------------- | --------------------- | ------------------- |
| Default resolution | 1080p | **720p** |
| Supported resolutions | 480p/720p/1080p | **480p/720p/1080p** |
| Duration range | 2-12s | **4-12s** |
| Audio generation | Not supported | **Supported** |
| Reference image | `reference` (1 image) | Not supported |
# seedance-2.0 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/seedance-2-0/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns task ID for subsequent queries
- Supports text-to-video, image-to-video (first frame/last frame)
- Supports reference video, reference audio, audio-enabled video
- Supports landscape, portrait, square, ultra-wide, and adaptive aspect ratios
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "seedance-2.0",
"prompt": "A kitten yawning at the camera",
"resolution": "720p",
"size": "16:9",
"duration": 5,
"generate_audio": true
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "seedance-2.0",
"prompt": "A kitten yawning at the camera",
"resolution": "720p",
"size": "16:9",
"duration": 5,
"generate_audio": True
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "seedance-2.0",
prompt: "A kitten yawning at the camera",
resolution: "720p",
size: "16:9",
duration: 5,
generate_audio: true
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "seedance-2.0",
"prompt": "A kitten yawning at the camera",
"resolution": "720p",
"size": "16:9",
"duration": 5,
"generate_audio": true,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "seedance-2.0",
"prompt": "A kitten yawning at the camera",
"resolution": "720p",
"size": "16:9",
"duration": 5,
"generate_audio": true
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"seedance-2.0",
"prompt" => "A kitten yawning at the camera",
"resolution" => "720p",
"size" => "16:9",
"duration" => 5,
"generate_audio" => true
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "seedance-2.0",
prompt: "A kitten yawning at the camera",
resolution: "720p",
size: "16:9",
duration: 5,
generate_audio: true
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "seedance-2.0",
"prompt": "A kitten yawning at the camera",
"resolution": "720p",
"size": "16:9",
"duration": 5,
"generate_audio": true
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""seedance-2.0"",
""prompt"": ""A kitten yawning at the camera"",
""resolution"": ""720p"",
""size"": ""16:9"",
""duration"": 5,
""generate_audio"": true
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KMCGF6BQGN3X28H3KSR50X5T"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
## Authentication
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `seedance-2.0` - Standard version, supports text-to-video, image-to-video, first/last frame video, reference video, reference audio, and audio-enabled video
* `seedance-2.0-fast` - Fast version, same features as the standard version with faster generation speed
* `seedance-2.0-mini` - Mini version, same features as the standard version
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Content reviewed:
* Text: `prompt`, `negative_prompt`
* Images: `image_urls`, `image_with_roles[].url`, `first_frame_image`, `last_frame_image`
* Image-type private `asset://` assets: resolve and review their original public URL
* Base64 images: review them after conversion to a public URL
`video_urls`, `audio_urls`, and video/audio private assets are **not reviewed**, because the moderation model does not support video or audio.
Supported model IDs: `seedance-2.0`, `seedance-2.0-fast`, `seedance-2.0-mini`, `seedance-2.0-face`, `seedance-2.0-fast-face`, `seedance-2-0` (legacy), and `seedance-2.5`.
The moderation call itself is not billed to the user submitting the video request.
* Flagged content returns a synchronous HTTP 400 (`nsfw_content_detected`). No task or `task_id` is created, and no video-generation quota is charged
* If moderation is unavailable, times out, or returns an invalid response, the request **fails open** and generation continues. Do not treat this option as an absolute content-safety guarantee
* Inputs that cannot be resolved to a public image URL are skipped; unsupported models silently ignore `nsfw_check: true`
Example:
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "a cat walking on the beach",
"image_urls": ["https://cdn.example.com/ref.png"],
"nsfw_check": true
}
```
Response when flagged:
```json theme={null}
{
"error": {
"message": "Your request was rejected by content moderation (`nsfw_check` is enabled). Flagged categories: sexual, violence/graphic.",
"type": "nsfw_content_detected",
"param": "",
"code": "nsfw_content_detected"
}
}
```
Video content description
Required for text-to-video; optional for image-to-video or video-reference-to-video
It is recommended to clearly specify the subject, action, camera movement, and style for better generation results
* The prompt is limited to 4000 characters, but 500 characters are recommended.
* The model `seedance-2.0-mini` has no character limit. Recommendation: keep Chinese prompts under 500 characters and English prompts under 1000 words. Excessive length tends to disperse the information, and the model may overlook details and focus only on the key points, resulting in some elements being missing from the video.
Example: `"A kitten yawning at the camera"`
Video duration (seconds)
Supported range: `4` to `15` seconds
Default: `5`
Video aspect ratio
The aspect ratio must be between 0.5 and 2.5
Options:
* `16:9` - Landscape
* `9:16` - Portrait
* `1:1` - Square
* `4:3` - Traditional ratio
* `3:4` - Vertical traditional ratio
* `21:9` - Ultra-wide
* `adaptive` - Adaptive (automatically matches the input image/video)
Default: `16:9`
Video resolution
Options:
* `480p` - Standard definition
* `720p` - High definition
* `1080p` - Full HD (only supported by `seedance-2.0`)
* `4k` - Ultra HD (only supported by `seedance-2.0`)
Default: `720p`
Random seed for controlling the randomness of generated content
* With the same request, different seed values will produce different results
* With the same request, the same seed value will produce similar results, but exact consistency is not guaranteed
Whether to generate audio (audio-enabled video)
When set to `true`, the video will include AI-generated accompanying audio
When set to `false`, the video will not include audio (silent video)
Default: `true`
Whether to return the last frame image
When set to `true`, the task result will additionally return the URL of the video's last frame image, which can be used for continuous video generation
Default: `false`
Tool list for enhanced capabilities such as web search
Example: `[{"type": "web_search"}]`
Tool type
Options:
* `web_search` - Web search, references online information during generation
Image URL array for image-to-video
Supports two formats:
* Regular image URL: `https://example.com/cat.jpg`
* Asset URL (approved asset): `asset://asset_a`
Example: `["https://example.com/cat.jpg"]` or `["asset://asset_a"]`
Asset URLs are supported by all Seedance 2.0 models: `seedance-2.0`, `seedance-2.0-fast`, and `seedance-2.0-mini`.
* `image_urls` and `image_with_roles` cannot be used simultaneously
* Maximum of 9 reference images
Image array with roles, supports specifying first frame/last frame
When the `url` field uses an Asset URL, all Seedance 2.0 models are supported: `seedance-2.0`, `seedance-2.0-fast`, and `seedance-2.0-mini`.
Image URL
Supports two formats:
* Regular image URL: `https://example.com/day.jpg`
* Asset URL (approved asset): `asset://asset_a`
Asset URLs are supported by all Seedance 2.0 models: `seedance-2.0`, `seedance-2.0-fast`, and `seedance-2.0-mini`.
Image role
Options:
* `first_frame` - First frame image, used as the video's starting frame
* `last_frame` - Last frame image, used as the video's ending frame
* `reference_image` - Reference portrait image (used with Asset URL)
Example:
```json theme={null}
[
{"url": "https://example.com/day.jpg", "role": "first_frame"},
{"url": "https://example.com/night.jpg", "role": "last_frame"}
]
```
Asset URL format:
```json theme={null}
[
{"url": "asset://asset_a", "role": "reference_image"}
]
```
* `image_urls` and `image_with_roles` cannot be used simultaneously
* When using first/last frame images, `video_urls` and `audio_urls` are not available
Reference video URL array
Supports two formats:
* Regular video URL: `https://example.com/reference.mp4`
* Asset URL (approved asset): `asset://asset_a`
Example: `["https://example.com/reference.mp4"]` or `["asset://asset_a"]`
Asset URLs are supported by all Seedance 2.0 models: `seedance-2.0`, `seedance-2.0-fast`, and `seedance-2.0-mini`.
* When using first/last frame images (`image_with_roles`), reference videos are not available
* Maximum of 3 reference videos, 1.8s \< total duration \< 15.2s
* Reference video resolution must be between 480P and 720P
Reference audio URL array
Supports two formats:
* Regular audio URL: `https://example.com/speech.wav`
* Asset URL (approved asset): `asset://asset_a`
Example: `["https://example.com/speech.wav"]` or `["asset://asset_a"]`
Asset URLs are supported by all Seedance 2.0 models: `seedance-2.0`, `seedance-2.0-fast`, and `seedance-2.0-mini`.
* When using first/last frame images (`image_with_roles`), reference audio is not available
* Maximum of 3 reference audio files, total duration must be 15s or less
* Reference audio must be used together with reference images or reference videos
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "A kitten yawning at the camera",
"resolution": "720p",
"size": "16:9",
"duration": 5,
"seed": 42,
"generate_audio": true
}
```
### Case 2: Image-to-Video (First Frame)
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "The kitten stands up and walks toward the camera",
"image_urls": ["https://example.com/cat.jpg"],
"duration": 5
}
```
### Case 3: First/Last Frame Video
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "Transition from day to night",
"image_with_roles": [
{"url": "https://example.com/day.jpg", "role": "first_frame"},
{"url": "https://example.com/night.jpg", "role": "last_frame"}
],
"duration": 5
}
```
### Case 4: Video-Reference-to-Video
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "Convert the video style to anime style",
"video_urls": ["https://example.com/reference.mp4"]
}
```
### Case 5: Reference Video + Reference Audio
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "A scene of a person speaking",
"video_urls": ["https://example.com/reference.mp4"],
"audio_urls": ["https://example.com/speech.wav"],
"size": "16:9",
"duration": 11
}
```
### Case 6: Audio-Enabled Video
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "A man stops a woman and says: \"Remember, you must never point your finger at the moon.\"",
"generate_audio": true
}
```
### Case 7: Continuous Video Generation (Return Last Frame)
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "The kitten continues walking toward the camera",
"image_urls": ["https://example.com/last_frame_from_prev.png"],
"return_last_frame": true
}
```
### Case 8: Fast Version Generation
```json theme={null}
{
"model": "seedance-2.0-fast",
"prompt": "City nightscape timelapse photography",
"size": "21:9",
"duration": 8
}
```
### Case 9: Reference Images + Reference Video + Reference Audio (Multi-Modal Video)
Combine reference images, reference video, and reference audio to generate an immersive first-person perspective advertisement video. Ideal for product promotions, brand ads, and other scenarios requiring multi-source material fusion.
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "Use video 1's first-person perspective throughout, and use audio 1 as the background music throughout. First-person POV fruit tea advertisement for seedance brand 'Peace Apple' apple fruit tea limited edition. First frame is image 1: your hand picks a dewy Aksu red apple with a crisp apple collision sound. 2-4s: quick cut, your hand drops apple chunks into a shaker cup, adds ice and tea base, shakes vigorously, ice collision and shaking sounds sync with upbeat drum beats, background voice: 'Fresh-cut, fresh-shaken'. 4-6s: first-person close-up of the finished product, layered fruit tea poured into a clear cup, your hand gently squeezes cream cap spreading on top, sticks a pink label on the cup, camera zooms in on the layered texture of cream cap and fruit tea. 6-8s: first-person handheld cup raise, you lift the fruit tea from image 2 toward the camera (simulating handing it to the viewer), cup label clearly visible, background voice 'Take a sip of freshness', final frame freezes on image 2. Background voice consistently uses a female tone.",
"image_urls": [
"https://example.com/tea_pic1.jpg",
"https://example.com/tea_pic2.jpg"
],
"video_urls": ["https://example.com/tea_video1.mp4"],
"audio_urls": ["https://example.com/tea_audio1.mp3"],
"generate_audio": true,
"size": "16:9",
"duration": 11
}
```
### Case 10: Image-to-Video with Asset URL
Approved virtual avatar assets can be passed directly as reference images without re-uploading or re-reviewing.
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "The character walks naturally on a city street under bright sunshine",
"image_urls": ["asset://asset_a"],
"duration": 5,
"resolution": "720p"
}
```
### Case 11: Specify Reference Portrait with Asset URL (image\_with\_roles)
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "Using the reference portrait, the character walks elegantly toward the camera",
"image_with_roles": [
{
"url": "asset://asset_a",
"role": "reference_image"
}
],
"resolution": "720p",
"duration": 5
}
```
### Case 12: Fast Version + Asset URL Image-to-Video
```json theme={null}
{
"model": "seedance-2.0-fast",
"prompt": "The character strolls in a park with a gentle breeze",
"image_urls": ["asset://asset_a"],
"duration": 5,
"resolution": "720p"
}
```
### Case 13: Asset URL Image + Reference Video (Motion Transfer)
Combine an approved portrait asset with a reference video to drive the character to perform specified movements.
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "The character dances to the rhythm of the reference video with smooth and natural movements",
"image_urls": ["https://example.com/dance_reference.jpg", "asset://asset_a"],
"video_urls": ["https://example.com/dance_reference.mp4", "asset://asset_a"],
"duration": 8,
"resolution": "720p"
}
```
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
## Differences from 1.5 Pro Version
| Feature | 1.5 Pro | 2.0 / 2.0 fast |
| ---------------------- | --------------------------------- | -------------------------------------------- |
| Resolution | 480p/720p/1080p | **480p/720p/1080p/4k** (fast only 480p/720p) |
| Duration range | 4-12s | **5-15s** |
| Default duration | 5s | **5s** |
| Aspect ratio parameter | `aspect_ratio` | **`size`** (new `adaptive` option) |
| Audio generation | `audio` parameter | **`generate_audio` parameter** |
| Reference video | Not supported | **Supported via `video_urls`** |
| Reference audio | Not supported | **Supported via `audio_urls`** |
| Image-to-video | `image_urls` / `image_with_roles` | **`image_urls` / `image_with_roles`** |
| Audio-enabled video | Not supported | **Supported via `generate_audio`** |
| Continuous video | Not supported | **Supported via `return_last_frame`** |
| Fast version | Not supported | **Supported via `seedance-2.0-fast`** |
# Virtual Avatar Assets
Source: https://docs.apimart.ai/en/api-reference/videos/seedance-2-0/private-avatar
POST https://api.apimart.ai/v1/seedance2/private-avatar
- Private-domain virtual avatar asset submission API
- Supports batch submission, up to 20 assets per request
- Automatically creates or reuses asset groups; returns a task ID for status polling
- Approved assets can be used directly in Seedance 2.0 video generation
```bash cURL (Batch submit · new group) theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/seedance2/private-avatar \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"group": {
"name": "virtual-avatar-group",
"description": "demo group"
},
"project_name": "default",
"asset_type": "Image",
"assets": [
{
"url": "https://example.com/avatar-a.png",
"name": "avatar-a"
},
{
"url": "https://example.com/avatar-b.png",
"name": "avatar-b"
}
]
}'
```
```bash cURL (Use existing group) theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/seedance2/private-avatar \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"group_id": "group_xxx",
"project_name": "default",
"asset_type": "Image",
"assets": [
{
"url": "https://example.com/avatar-a.png",
"name": "avatar-a"
}
]
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/seedance2/private-avatar"
payload = {
"group": {
"name": "virtual-avatar-group",
"description": "demo group"
},
"project_name": "default",
"asset_type": "Image",
"assets": [
{
"url": "https://example.com/avatar-a.png",
"name": "avatar-a"
},
{
"url": "https://example.com/avatar-b.png",
"name": "avatar-b"
}
]
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/seedance2/private-avatar";
const payload = {
group: {
name: "virtual-avatar-group",
description: "demo group"
},
project_name: "default",
asset_type: "Image",
assets: [
{
url: "https://example.com/avatar-a.png",
name: "avatar-a"
},
{
url: "https://example.com/avatar-b.png",
name: "avatar-b"
}
]
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": {
"id": "task_01K...",
"object": "seedance.avatar.asset.task",
"status": "processing",
"progress": 10,
"model": "seedance-2.0"
}
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Please check your API key.",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance. Please top up and try again.",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests. Please try again later.",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later.",
"type": "server_error"
}
}
```
## Authentication
All requests require Bearer Token authentication
Get your API Key:
Visit the [API Key Management page](https://apimart.ai/keys) to obtain your API Key
Add the following header to each request:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Asset group information
If `group_id` is not provided, the server will automatically create an `AIGC` asset group based on this field
Asset group name
Asset group description
Example:
```json theme={null}
{
"group": {
"name": "virtual-avatar-group",
"description": "demo group"
}
}
```
Mutually exclusive with `group_id` — do not provide both at the same time
Existing asset group ID
When provided, skips group creation and submits assets directly to the specified group
Mutually exclusive with `group` — do not provide both at the same time
Project name
Default: `default`
Asset type
Options:
* `Image` - Image asset (default)
* `Video` - Video asset
* `Audio` - Audio asset
Default: `Image`
Asset list, supports submitting multiple assets in one request
Maximum **20** assets per submission
Asset URL — must be publicly accessible
Asset name
Example:
```json theme={null}
{
"assets": [
{
"url": "https://example.com/avatar-a.png",
"name": "avatar-a"
},
{
"url": "https://example.com/avatar-b.png",
"name": "avatar-b"
}
]
}
```
Single-asset shorthand: asset URL
Use either `assets` array or this field — not both. Suitable for submitting a single asset.
Single-asset shorthand: asset name
Use either `assets` array or this field — not both. Suitable for submitting a single asset.
## Response
Response status code, 200 on success
Task information
Local task ID, used to query asset review status
Task object type, always `seedance.avatar.asset.task`
Initial task status, `processing` after submission
Task progress (0 \~ 100)
Model name in use
## Examples
### Example 1: Batch submit (auto-create group)
When `group_id` is not provided, the server automatically creates an `AIGC` asset group before submitting.
```json theme={null}
{
"group": {
"name": "virtual-avatar-group",
"description": "demo group"
},
"project_name": "default",
"asset_type": "Image",
"assets": [
{
"url": "https://example.com/avatar-a.png",
"name": "avatar-a"
},
{
"url": "https://example.com/avatar-b.png",
"name": "avatar-b"
}
]
}
```
### Example 2: Append assets to an existing group
Provide `group_id` to skip group creation and submit directly.
```json theme={null}
{
"group_id": "group_xxx",
"project_name": "default",
"asset_type": "Image",
"assets": [
{
"url": "https://example.com/avatar-a.png",
"name": "avatar-a"
}
]
}
```
### Example 3: Single-asset shorthand
For a single asset, use the top-level `url` and `name` fields directly.
```json theme={null}
{
"group_id": "group_xxx",
"url": "https://example.com/avatar.png",
"asset_type": "Image",
"name": "avatar-1"
}
```
## Query Review Result
Asset submission is an asynchronous task. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to poll:
```http theme={null}
GET /v1/tasks/{id}
```
### All Approved
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01K...",
"status": "completed",
"progress": 100,
"result": {
"assets": [
{
"asset_id": "asset_a",
"asset_url": "asset://asset_a",
"status": "Active"
},
{
"asset_id": "asset_b",
"asset_url": "asset://asset_b",
"status": "Active"
}
],
"usable_assets": [
{
"asset_id": "asset_a",
"asset_url": "asset://asset_a",
"status": "Active"
},
{
"asset_id": "asset_b",
"asset_url": "asset://asset_b",
"status": "Active"
}
],
"failed_assets": []
}
}
}
```
### Partial Failure
If any asset fails review, the task status becomes `failed`. Successfully approved assets remain usable and appear in `result.usable_assets`.
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01K...",
"status": "failed",
"progress": 100,
"result": {
"assets": [
{
"asset_id": "asset_a",
"asset_url": "asset://asset_a",
"status": "Active"
},
{
"asset_id": "asset_b",
"asset_url": "asset://asset_b",
"status": "Failed"
}
],
"usable_assets": [
{
"asset_id": "asset_a",
"asset_url": "asset://asset_a",
"status": "Active"
}
],
"failed_assets": [
{
"asset_id": "asset_b",
"asset_url": "asset://asset_b",
"status": "Failed"
}
]
},
"error": {
"code": "task_failed",
"message": "Some assets failed review"
}
}
}
```
* `result.usable_assets[].asset_url` can be used directly in Seedance 2.0 video generation
* Assets in `result.failed_assets` must be replaced or resubmitted
* Single-asset tasks also return `result.asset_url` for compatibility
## Using Approved Assets
Pass the `asset://...` URL directly to the [Seedance 2.0 Video Generation](/en/api-reference/videos/seedance-2-0/generation) endpoint:
```json theme={null}
{
"model": "seedance-2.0",
"prompt": "The character walks naturally along a city street",
"image_urls": ["asset://asset_a"],
"duration": 5,
"resolution": "720p"
}
```
Once the server detects the `asset://` prefix, it submits the generation task directly without triggering another asset review.
# seedance-2.5 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/seedance-2-5/generation
POST https://api.apimart.ai/v1/videos/generations
- Async API; returns task_id for polling
- Text-to-video / multimodal reference / edit / extend / first–last frame
- Up to 30s per job; up to 30 images + 10 videos + 10 audios as references
- Resolution supports 480p / 720p / 1080p; mp4 or mov output
**Main changes vs 2.0**: max duration 15s → **30s**; references 9 images + 3 videos + 3 audios → **30 images + 10 videos + 10 audios**; **audio-only** reference supported; **mov** output added.\
**Note**: resolution supports **480p / 720p / 1080p** (2.0’s 4k is **not** available on 2.5).
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "seedance-2.5",
"prompt": "A cinematic 30-second steampunk miniature landscape sequence",
"size": "16:9",
"resolution": "720p",
"duration": 30
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "seedance-2.5",
"prompt": "A cinematic 30-second steampunk miniature landscape sequence",
"size": "16:9",
"resolution": "720p",
"duration": 30,
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "seedance-2.5",
prompt: "A cinematic 30-second steampunk miniature landscape sequence",
size: "16:9",
resolution: "720p",
duration: 30,
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "seedance-2.5",
"prompt": "A cinematic 30-second steampunk miniature landscape sequence",
"size": "16:9",
"resolution": "720p",
"duration": 30,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "seedance-2.5",
"prompt": "A cinematic 30-second steampunk miniature landscape sequence",
"size": "16:9",
"resolution": "720p",
"duration": 30
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"seedance-2.5",
"prompt" => "A cinematic 30-second steampunk miniature landscape sequence",
"size" => "16:9",
"resolution" => "720p",
"duration" => 30
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KMCGF6BQGN3X28H3KSR50X5T"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up and try again",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authentication
Bearer token auth. Get a key from the [API Key page](https://apimart.ai/keys).
```
Authorization: Bearer YOUR_API_KEY
```
## Request parameters
Fixed value: `seedance-2.5`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Content reviewed:
* Text: `prompt`, `negative_prompt`
* Images: `image_urls`, `image_with_roles[].url`, `first_frame_image`, `last_frame_image`
* Image-type private `asset://` assets: resolve and review their original public URL
* Base64 images: review them after conversion to a public URL
`video_urls`, `audio_urls`, and video/audio private assets are **not reviewed**, because the moderation model does not support video or audio.
Supported model IDs: `seedance-2.0`, `seedance-2.0-fast`, `seedance-2.0-mini`, `seedance-2.0-face`, `seedance-2.0-fast-face`, `seedance-2-0` (legacy), and `seedance-2.5`.
The moderation call itself is not billed to the user submitting the video request.
* Flagged content returns a synchronous HTTP 400 (`nsfw_content_detected`). No task or `task_id` is created, and no video-generation quota is charged
* If moderation is unavailable, times out, or returns an invalid response, the request **fails open** and generation continues. Do not treat this option as an absolute content-safety guarantee
* Inputs that cannot be resolved to a public image URL are skipped; unsupported models silently ignore `nsfw_check: true`
Example:
```json theme={null}
{
"model": "seedance-2.5",
"prompt": "a cat walking on the beach",
"image_urls": ["https://cdn.example.com/ref.png"],
"nsfw_check": true
}
```
Response when flagged:
```json theme={null}
{
"error": {
"message": "Your request was rejected by content moderation (`nsfw_check` is enabled). Flagged categories: sexual, violence/graphic.",
"type": "nsfw_content_detected",
"param": "",
"code": "nsfw_content_detected"
}
}
```
Prompt. Reference media with `@图片1` / `@视频1` / `@音频1` (1-based index matching array order). English aliases in prompts may also be used depending on model behavior; keep indices aligned with arrays.
Example: `"Use @视频1 for first-person framing throughout, @音频1 as BGM, first frame is @图片1"`
Resolution — **only**:
* `480p`
* `720p` (default)
* `1080p`
Unsupported values like `2k` / `4k` return a sync **400**.
Aspect ratio (field name `aspect_ratio` is also accepted).
Values: `16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `21:9`, `adaptive` (default)
Edit, extend, and first/last-frame jobs have hard `size` constraints — see [Task types and constraints](#task-types-and-constraints).
Duration in seconds:
* `4` \~ `30`
* `-1`: model picks duration (pre-charge at the **30s** cap; settle to actual length after completion)
If omitted: generate and bill **5** seconds.
Whether to generate audio (alias field name: `audio`).
* `true`: with audio (default)
* `false`: silent video
Add an “AI generated” watermark. Default `false`.
Random seed. Different seeds usually yield different results for the same request; the same seed is similar but not guaranteed identical.
Output container:
* `mp4` (default)
* `mov`: higher color precision — **recommended** for edit / extend workflows
Sub-task type hint: `auto` / `reference` / `edit` / `extend`.
Passing `reference` / `edit` / `extend` validates that type’s constraints **at submit time**. Invalid requests return **400**, create no task, and charge nothing. See [Task types and constraints](#task-types-and-constraints).
Reference image URLs, all treated as `reference_image`.
Supports:
* Public URL: `https://example.com/pic.jpg`
* Private asset: `asset://cm9xxxxxxxx`
For first/last frames use `image_with_roles`.
* Max **30** images
* Prefer `image_with_roles` for first/last-frame roles
Images with explicit roles.
Image URL or `asset://...`
* `first_frame`: first frame (1 image)
* `last_frame`: last frame (1 image, usually with first frame)
* `reference_image`: reference image (up to 30 total)
Example:
```json theme={null}
[
{"url": "https://example.com/first.jpg", "role": "first_frame"},
{"url": "https://example.com/last.jpg", "role": "last_frame"}
]
```
If `video_urls` / `audio_urls` are present, `first_frame` / `last_frame` are auto-converted to `reference_image` (multimodal reference job).
Reference videos (`reference_video`).
**Input**: video URL or asset ID (`asset://...`).
See [Reference video specs](#reference-video-specs).
Reference audio URLs (`reference_audio`). Public URLs or `asset://...`.
Max **10**; total duration ≤ **30s** (each clip 2\~30s).
2.5 supports **audio-only** reference (no image/video required).
When `true`, the successful result also includes the last-frame image for chaining.
Tool list for enhancements such as web search.
Example:
```json theme={null}
"tools": [{"type": "web_search"}]
```
Tool type
Values:
* `web_search` — web search; generation can ground on online information
## Media limits
| Media | Limits |
| ------ | -------------------------------------------------------------------------------------------------------------------------- |
| Images | ≤30; jpeg / png / webp / bmp / tiff / gif / heic / heif; aspect ratio \[0.4, 2.5]; side length \[300, 6000]px; each \<30MB |
| Videos | See [Reference video specs](#reference-video-specs) |
| Audio | ≤10; wav / mp3; each \[2, 30]s and **total ≤30s**; each ≤15MB |
### Reference video specs
* **Input**: video URL or asset ID (`asset://...`)
* **Container**: `mp4`, `mov` — codecs in the table below
* **Resolution**: `480p`, `720p`, `1080p`
* **Duration**: each clip \[2, 30] s; up to **10** reference videos; **total duration of all videos ≤ 30s**
* **Per-video dimensions**:
* Aspect ratio (width/height): \[0.4, 2.5]
* Side length (px): \[300, 6000]
* Total pixels: \[640×640=409600, 3326×2494=8295044], i.e. width × height must fall in \[409600, 8295044]
* **Size**: each video ≤ **200 MB**
* **Frame rate (FPS)**: \[24, 60]
#### Supported codecs
| Container | Video codec | Audio codec |
| --------- | ------------- | ----------- |
| `mp4` | H.264 / H.265 | AAC / MP3 |
| `mov` | H.264 / H.265 | AAC / MP3 |
## Task types and constraints
The service infers task type from references and **prompt intent**. The last three types hard-constrain `size` / `duration`; violations fail **asynchronously after the job starts** (e.g. `InvalidParameter.TaskTypeConstraint`):
| Task type | Trigger | Constraints |
| ------------------------ | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Text-to-video | Text only | None |
| Reference-to-video | References + normal descriptive prompt | None. **Avoid** words like “edit / extend / continue / delete / replace” in the prompt to prevent misclassification |
| Video edit | References + prompt with “edit video / add / delete / modify / replace”, etc. | `size` must be `adaptive`, `duration` must be `-1`; source video 4\~30s |
| Video extend | References + prompt with “extend forward/backward / continue / sequel” | `size` must be `adaptive` |
| First / first–last frame | `image_with_roles` uses `first_frame` / `last_frame` | `size` must be `adaptive` (also checked at submit time) |
### Turn async errors into sync errors with `omni_reference_task_type`
Passing `reference` / `edit` / `extend` declares the sub-task type so its constraints are **validated at submit time**. Invalid requests return 400 immediately: no task is created and nothing is charged — you do not have to poll until `failed`.
| Value | Meaning | Constraints checked at submit |
| ---------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `auto` (default) | Model infers the type | None (violations fail **asynchronously**) |
| `reference` | Reference-to-video | None (`size` / `duration` unrestricted) |
| `edit` | Video edit | At least one item in `video_urls`; `size` must be `adaptive` (or omitted); `duration` must be `-1` (or omitted, see below); source video 4\~30s |
| `extend` | Video extend | At least one item in `video_urls`; `size` must be `adaptive` (or omitted) |
Notes:
* **If `edit` omits `duration`, the platform sets it to `-1`.** Omitting `duration` otherwise defaults to 5 seconds, which conflicts with the upstream `edit` requirement of `-1`. The trade-off is a **30-second prepaid hold** (same as `duration: -1`); unused amount is refunded after completion. For a smaller hold, skip `edit` and use default `auto`.
* **If `edit` sends `duration` explicitly, it must be `-1`.** Any other value returns 400 (output length follows the source video).
* ⚠️ **You can still fail asynchronously with `InvalidParameter.TaskTypeMismatch`.** Upstream re-classifies the job from the prompt; a mismatch with your declared type is rejected. Keep prompt wording aligned (`edit`: “edit / delete / replace…”; `extend`: “extend forward/backward / continue…”).
* All Seedance 2.5 channels share the same validation and upstream payload; switching channels does not change this behavior.
## Asset library
You can pass public URLs as references, or upload into the library first and use `asset://`. **Prefer the library** when:
1. **Real human faces must use the library** — raw URLs are blocked by content moderation; only approved library assets can be used
2. **Assets are reused often** — upload once, skip repeated moderation on later jobs, faster submits
3. **URLs are signed temporary links** — the platform stores a durable copy on ingest so later use does not depend on the original URL staying alive
4. Library assets are **synced to all available channels** so multi-channel routing can use them wherever the job lands
The library is **shared** with the 2.0 family; approved `asset://` IDs work in both 2.0 and 2.5 generation requests. Full submit fields: also see [Private avatar assets](/en/api-reference/videos/seedance-2-0/private-avatar).
### Upload assets
```bash theme={null}
POST /v1/seedance2/private-avatar/assets
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```
```bash theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/seedance2/private-avatar/assets \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "seedance-2.5",
"group": { "name": "my-assets" },
"asset_type": "Image",
"assets": [
{ "url": "https://example.com/a.png", "name": "a" },
{ "url": "https://example.com/b.png", "name": "b" }
]
}'
```
| Field | Required | Description |
| --------------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `model` | No | Model the assets will be used with (defaults to 2.0). **Sets the duration tier**; for 2.5 pass `seedance-2.5` |
| `group` | No | Asset group; created automatically if omitted |
| `asset_type` | Yes | `Image` / `Video` / `Audio` |
| `assets[].url` | Yes | Public media URL |
| `assets[].name` | No | Asset name |
The response includes a local task `id`. Poll with [Get task status](/en/api-reference/tasks/status) (`GET /v1/tasks/{id}`). After approval, list assets to obtain the `asset://` ID.
### Media limits (validated at submit)
Violations return **400 immediately** (which asset index and which rule), without starting moderation or consuming moderation quota:
| Media | Limits |
| ----- | --------------------------------------------------------------------------------------------------------------------- |
| Image | jpeg / png / webp / bmp / tiff / gif / heic / heif; side length \[300, 6000]px; aspect ratio \[0.4, 2.5]; each \<30MB |
| Video | mp4 / mov; each ≤200MB; duration **by model**: 2.0 family \[2, 15]s, **2.5 \[2, 30]s** |
| Audio | wav / mp3; each ≤15MB; duration tiers same as video |
Error example:
```json theme={null}
{
"error": {
"code": "invalid_asset_material",
"message": "video #1: duration must be between 2s and 15s for seedance-2.0 (got 30s)"
}
}
```
For 30s video assets, submit with `"model": "seedance-2.5"` (2.0 cannot use assets longer than 15s).\
If the platform cannot probe the media (e.g. network blip), it may pass through and leave the decision to moderation.
### Use in generation requests
Reference approved assets with `asset://` in `image_urls` / `image_with_roles` / `video_urls` / `audio_urls`:
```json theme={null}
{
"model": "seedance-2.5",
"prompt": "The person in @图片1 walks along the beach",
"image_urls": ["asset://cm9xxxxxxxx"],
"duration": 8
}
```
Multi-channel: after ingest, assets sync to all available channels so any routed channel can use them. If a channel’s copy is missing, the platform may re-upload from the original URL as a fallback (if that URL is already expired, that channel is skipped and another takes over).
### Management APIs (quick reference)
| Method | Path | Purpose |
| ----------------------------------- | ------------------------------------------------ | -------------------------------------- |
| `GET` | `/v1/seedance2/private-avatar/assets` | List assets |
| `GET` | `/v1/seedance2/private-avatar/assets/{asset_id}` | Asset detail (incl. moderation status) |
| `PATCH` | `/v1/seedance2/private-avatar/assets/{asset_id}` | Update asset metadata |
| `DELETE` | `/v1/seedance2/private-avatar/assets/{asset_id}` | Delete asset |
| `POST` / `GET` / `PATCH` / `DELETE` | `/v1/seedance2/private-avatar/groups[/{id}]` | Asset group management |
Asset APIs are **free of charge** (auth + rate limits only); they do not create billing records.
### FAQ
**Q: How long does moderation take?**\
Images usually seconds; video and real-person assets may take minutes. Poll the task `id` until a terminal status.
**Q: Moderation failed with no clear reason?**\
Some failures omit a detailed reason (often a transient fetch failure). The platform already retries once; if it still fails, change the URL (ensure it is publicly downloadable) and resubmit.
**Q: Same asset for both 2.0 and 2.5 — upload twice?**\
No. Upload once; `asset://` works for both generations. Cross-channel / cross-model sync is handled by the platform.
**Q: Can I pass a real-person face as a raw URL?**\
Real-person assets must go through the library first.
## Billing
* Billed by **seconds × resolution tier**.
* **With reference video input**: billable seconds = total input video duration (≤30s) + output duration, at the input-reference rate tier.
* `duration = -1` (auto): pre-charge at the **30s** cap; settle to actual output after completion.
* Omit `duration`: generate and bill **5** seconds.
* Failed jobs or content moderation blocks: **full refund** (charge only on successful output).
## Request examples
### Text-to-video (30s)
```json theme={null}
{
"model": "seedance-2.5",
"prompt": "A cinematic 30-second steampunk miniature landscape sequence",
"size": "16:9",
"resolution": "720p",
"duration": 30
}
```
### Multimodal reference (image + video + audio)
```json theme={null}
{
"model": "seedance-2.5",
"prompt": "Use @视频1 for first-person framing, @音频1 as BGM, first frame is @图片1",
"image_urls": [
"https://example.com/pic1.jpg",
"https://example.com/pic2.jpg"
],
"video_urls": ["https://example.com/ref.mp4"],
"audio_urls": ["https://example.com/bgm.mp3"],
"size": "16:9",
"duration": 11
}
```
### Video edit
```json theme={null}
{
"model": "seedance-2.5",
"prompt": "Edit the video: remove all passers-by in @视频1, keep only the main character",
"video_urls": ["https://example.com/input.mp4"],
"size": "adaptive",
"duration": -1,
"output_format": "mov"
}
```
### First–last frame
```json theme={null}
{
"model": "seedance-2.5",
"prompt": "The girl in the image says \"cheese\" to the camera, 360-degree orbit shot",
"image_with_roles": [
{"url": "https://example.com/first.jpg", "role": "first_frame"},
{"url": "https://example.com/last.jpg", "role": "last_frame"}
],
"size": "adaptive",
"duration": 5
}
```
### Private asset
```json theme={null}
{
"model": "seedance-2.5",
"prompt": "A person walking naturally on a city street in sunlight",
"image_urls": ["asset://cm9xxxxxxxx"],
"duration": 5,
"resolution": "720p"
}
```
### Web search
```json theme={null}
{
"model": "seedance-2.5",
"prompt": "Generate a short tech-news video intro based on the latest information",
"size": "16:9",
"resolution": "720p",
"duration": 8,
"tools": [{"type": "web_search"}]
}
```
## Common errors
| Symptom | Cause |
| -------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| 400 unsupported `resolution` | Passed unsupported values such as `2k` / `4k` |
| 400 `This model only supports duration 4-30 seconds, or -1` | `duration` out of range |
| 400 `first_frame/last_frame tasks only support ratio=adaptive` | First/last-frame job with a fixed aspect ratio |
| Async failure (edit / extend style message) | Prompt classified as edit/extend but `size` / `duration` violate that type’s rules |
| Async failure `SensitiveContentDetected` | Media or output failed moderation |
## Response (submit)
Status code; `200` on success
Submit response with `status` / `task_id`
Initially `submitted`
Task ID for [status polling](/en/api-reference/tasks/status)
## Completed task (`GET /v1/tasks/{task_id}`)
After submit, poll with [Get task status](/en/api-reference/tasks/status). When `status` is `completed`, the payload looks like this.
### Completed response example
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KZEWTMH6TG3Z1X2QRP2B9ZG9",
"status": "completed",
"progress": 100,
"created": 1786132648,
"completed": 1786132748,
"actual_time": 100,
"estimated_time": 300,
"cost": 0.3104,
"credits_cost": 3.104,
"usage": {
"completion_tokens": 38800
},
"result": {
"videos": [
{
"url": [
"https://cdn.example.com/video/…-video_task_01KZEWTMH6TG3Z1X2QRP2B9ZG9.mp4"
],
"expires_at": 1786219148
}
]
}
}
}
```
### Completed fields
| Field | Type | Description |
| ------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------- |
| `data.id` | string | Task ID |
| `data.status` | string | Always `completed` when done |
| `data.progress` | int | Always `100` when done |
| `data.created` / `data.completed` | int | Submit / finish time (Unix seconds) |
| `data.actual_time` | int | Elapsed seconds = completed − created |
| `data.estimated_time` | int | Platform ETA in seconds (reference only) |
| `data.cost` | float | **Actual charge in USD** for this job (includes discounts; matches billing logs) |
| `data.credits_cost` | float | Credits charged = `cost × 10` |
| `data.usage.completion_tokens` | int | Tokens consumed. Settlement: `cost = completion_tokens ÷ 10⁶ × token unit price × discount` |
| `data.result.videos[].url` | **string\[]** | Video URL(s). **This is an array** — use `url[0]`. Values are **long-lived platform CDN URLs** after re-hosting |
| `data.result.videos[].expires_at` | int | Expiry timestamp (kept for compatibility; re-hosted URLs are long-lived) |
| `data.result.videos[].last_frame_url` | string | Last-frame image (only if submit used `return_last_frame=true`) |
### Notes
* Failed tasks (`status=failed`): `cost` is always `0` (pre-charge fully refunded); reason in `data.error.message`
* `usage` may be missing for a few seconds after completion (settlement lag); query again shortly
## Differences from 2.0
| Feature | 2.0 | 2.5 |
| ------------------ | ------------------------ | ------------------------------------- |
| Model | `seedance-2.0`, etc. | `seedance-2.5` |
| Duration | \~4–15s | **4–30s**, or `-1` auto |
| Resolution | 480p / 720p / 1080p / 4k | **480p / 720p / 1080p** |
| Reference images | ≤9 | **≤30** |
| Reference videos | ≤3, total \~\<15s | **≤10, total ≤30s** |
| Reference audio | ≤3, total ≤15s | **≤10, total ≤30s**; audio-only OK |
| Output format | Mainly mp4 | **mp4 / mov** |
| Watermark | — | `watermark` |
| Private `asset://` | Supported | **Shared** with the same private APIs |
# SkyReels V4 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/skyreels-v4/generation
POST https://api.apimart.ai/v1/videos/generations
- Two model tiers: Fast (speed-optimized) and Std (quality-optimized)
- Three modes auto-routed by request fields: Text-to-Video (T2V), Image-to-Video (I2V), Multimodal Reference (Omni)
- 480p / 720p / 1080p resolution, 3 ~ 15 seconds duration
- Advanced features: first/end/key frame, reference images, reference videos, grid collage, video extension, audio sync
- Async processing mode, returns a task ID for later query
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": True
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "skyreels-v4-fast",
prompt: "A serene forest at sunset with golden light filtering through the trees.",
duration: 5,
resolution: "1080p",
aspect_ratio: "16:9",
prompt_optimizer: true
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"skyreels-v4-fast",
"prompt" => "A serene forest at sunset with golden light filtering through the trees.",
"duration" => 5,
"resolution" => "1080p",
"aspect_ratio" => "16:9",
"prompt_optimizer" => true
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "skyreels-v4-fast",
prompt: "A serene forest at sunset with golden light filtering through the trees.",
duration: 5,
resolution: "1080p",
aspect_ratio: "16:9",
prompt_optimizer: true
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""skyreels-v4-fast"",
""prompt"": ""A serene forest at sunset with golden light filtering through the trees."",
""duration"": 5,
""resolution"": ""1080p"",
""aspect_ratio"": ""16:9"",
""prompt_optimizer"": true
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KPEY5H3NQ2W8D7T6VB3F9GR4"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 422 theme={null}
{
"error": {
"code": 422,
"message": "Parameter conflict or invalid value (e.g. I2V and Omni fields passed simultaneously)",
"type": "invalid_request_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please retry later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Generation Modes
SkyReels V4 auto-routes to the correct mode based on request fields — **no `mode` field needed**:
| Mode | Trigger | Capability |
| ------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| **T2V** (Text-to-Video) | Only `prompt` + general fields | Pure text-driven generation |
| **I2V** (Image-to-Video) | Any of `first_frame_image` / `end_frame_image` / `mid_frame_images` | First/end/key frame control |
| **Omni** (Multimodal Reference) | Any of `ref_images` / `ref_videos` | Subject reference, grid collage, motion reference, video extension, audio sync |
**Strict mutual exclusion**: I2V fields (`first_frame_image` / `end_frame_image` / `mid_frame_images`) and Omni fields (`ref_images` / `ref_videos`) cannot be used together, otherwise returns 422.
**`@tag` mechanism**: When using `mid_frame_images` / `ref_images` / `ref_videos`, each element must declare a `tag` starting with `@` (e.g., `@image1`, `@Actor-1`, `@video1`), and the `tag` **must appear in the `prompt`**.
Think of `prompt` as the "script" and `tag` as a "character pointer" to specific assets (images / videos). For example, a prompt like `"@Actor-1 walks into the scene of @video1"` instructs the system to inject the reference image subject tied to `@Actor-1` and the motion reference tied to `@video1` into the generation process.
## Request Parameters
### General Fields
Two model tiers are available:
| Model | Positioning | Use Cases |
| ------------------ | ---------------------------------------------- | ---------------------------------------------------- |
| `skyreels-v4-fast` | Speed-first | Quick previews, batch generation, daily content |
| `skyreels-v4-std` | Quality-first (25\~30% higher price than Fast) | Key shots, high-detail requirements, formal delivery |
**The `model` field must be explicitly provided — no default value.**
**Pricing is strongly tied to resolution and whether `ref_videos` is used**: 1080p is significantly more expensive than 480p / 720p; tiers with `ref_videos` (video input) cost \~1.5 \~ 2× compared to those without. Simultaneous audio and video output is not yet supported.
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text prompt, max **1280 tokens**
Describe scenes, subjects, actions, styles in detail for better generation results.
When using `ref_images` / `ref_videos` / `mid_frame_images`, the `prompt` **must contain** the corresponding `@tag` (e.g., `@Actor-1`, `@video1`, `@image1`).
Example: `"@Actor-1 walks through a neon-lit street at night."`
Output video duration (seconds)
* Range: `[3, 15]`
* Default: `5`
When `ref_videos.type=reference` is provided, `duration` is overridden by the reference video length (max 10 seconds).
Video resolution
Options:
* `480p`
* `720p`
* `1080p` (default)
Aspect ratio
Options:
* `16:9` (default)
* `4:3`
* `1:1`
* `9:16`
* `3:4`
**`aspect_ratio` is ignored in I2V mode** (output ratio is determined by the input image); also ignored when Omni is combined with `ref_videos`.
Whether to auto-optimize the prompt
When enabled, the system automatically optimizes your prompt for better generation results.
### I2V-Specific Fields
First frame image URL (jpg / jpeg / png / gif / bmp)
When provided, this image is used as the **starting frame** of the video.
End frame image URL (jpg / jpeg / png / gif / bmp)
When provided, this image is used as the **ending frame** of the video. Can be combined with `first_frame_image` for first-and-last-frame control.
Mid keyframe list, **up to 6**. Each element has the following structure:
Must start with `@` and appear in the `prompt`, e.g., `@image1`
Image URL (jpg / jpeg / png / gif / bmp)
Timestamp of appearance (seconds). Default `-1` (unspecified); when specified, must satisfy `0 < time_stamp < duration`.
### Omni-Specific Fields
Reference image list (all elements must share the same `type`). Each element has the following structure:
Must start with `@` and appear in the `prompt`, e.g., `@Actor-1`
Reference type:
* `image` - Regular reference image (list length 1~~3; each `image_urls` length 1~~5)
* `grid` - Grid collage, i.e., a single image composed of multiple tiles (e.g., 2×2, 3×3); list length must = 1, `image_urls` must be 1 image
Array of image URLs
Voice audio URL (**only supported when `type=image`**, audio duration ≤ 15 seconds)
Reference video list, **up to 1**. Each element has the following structure:
Must start with `@` and appear in the `prompt`, e.g., `@video1`
Reference type:
* `reference` - Motion / subject reference, **overrides `duration`** (follows the reference video length, max 10 seconds), carries input video audio by default; **can be combined with `ref_images.type=image`**
* `extend` - Video extension, billed by the requested `duration`; **cannot be combined with `ref_images`**
Video URL (MP4 / MOV, duration ≤ 15 seconds)
## Supported Scenarios
The following scenarios are **supported by both** `skyreels-v4-fast` and `skyreels-v4-std`:
| Scenario | Mode | Required Fields | Typical Use Case |
| ---------------------------- | ---- | ----------------------------------------- | ------------------------------------------------------------ |
| Text-to-Video | T2V | `prompt` | Pure text-driven, rapid concept shots |
| Image-to-Video - First Frame | I2V | `first_frame_image` | Still-to-video with a specified starting frame |
| Image-to-Video - End Frame | I2V | `end_frame_image` | Specifies the closing frame |
| Image-to-Video - Keyframes | I2V | `mid_frame_images` (1 \~ 6) | First + end + mid keyframes for precise pacing |
| Omni Single/Multi-Subject | Omni | `ref_images` (`type=image`) | Character consistency, multi-subject framing |
| Omni Grid Collage | Omni | `ref_images` (`type=grid`, 1 image) | Step-by-step process videos (tutorials, recipes, demos) |
| Omni Motion Reference | Omni | `ref_videos` (`type=reference`) | Replicate the motion, subject, or style of a reference video |
| Omni Video Extension | Omni | `ref_videos` (`type=extend`) | Continue an existing video with new content |
| Omni Audio Sync | Omni | `ref_images` (`type=image`) + `audio_url` | Digital human narration, audio-driven lip-sync |
## Parameter Constraints
Violating any of the following will cause the request to be rejected with a **422** response, **no billing occurs**:
| Parameter | Constraint |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `prompt` | Max 1280 tokens |
| `duration` | `[3, 15]` seconds; overridden by reference video length (max 10s) when `ref_videos.type=reference` |
| `resolution` | Only `480p` / `720p` / `1080p` |
| `aspect_ratio` | `16:9` / `4:3` / `1:1` / `9:16` / `3:4`; ignored in I2V; ignored when Omni carries `ref_videos` |
| `mid_frame_images` | Up to 6; `time_stamp` must be `-1` or within `(0, duration)` |
| `ref_images` overall | All elements must share the same `type`; cannot coexist with I2V fields |
| `ref_images.type=grid` | List length must = 1; `image_urls` must be 1 image |
| `ref_images.type=image` | List length 1 \~ 3; each `image_urls` length 1 \~ 5 |
| `ref_images.audio_url` | Only supported when `type=image`, audio ≤ 15 seconds |
| `ref_videos` | Up to 1; `video_url` MP4 / MOV, ≤ 15 seconds |
| `ref_videos.type=reference` | Overrides requested `duration` (max 10s), can combine with `ref_images.type=image`, carries input video audio by default |
| `ref_videos.type=extend` | Billed by requested `duration`; **cannot combine with `ref_images`** |
| `tag` field | Must start with `@` and appear in the `prompt` |
| I2V / Omni exclusion | I2V fields and Omni fields cannot be used together |
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Request Examples
### Case 1: Text-to-Video (Minimal)
```json theme={null}
{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees."
}
```
### Case 2: Text-to-Video (Full Parameters)
```json theme={null}
{
"model": "skyreels-v4-std",
"prompt": "A serene forest at sunset.",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
}
```
### Case 3: Image-to-Video - First Frame
```json theme={null}
{
"model": "skyreels-v4-fast",
"prompt": "Slowly pull the camera back to reveal the entire scene.",
"first_frame_image": "https://example.com/start.png",
"duration": 5
}
```
### Case 4: Image-to-Video - First/End Frame + Mid Keyframes
```json theme={null}
{
"model": "skyreels-v4-std",
"prompt": "The King summons a flying dragon. @image1 The dragon lowers. The King mounts and flies away.",
"duration": 8,
"resolution": "1080p",
"first_frame_image": "https://example.com/k2v_0.png",
"end_frame_image": "https://example.com/k2v_2.png",
"mid_frame_images": [
{ "tag": "@image1", "image_url": "https://example.com/k2v_1.png", "time_stamp": 3 }
]
}
```
### Case 5: Omni - Single Subject Reference
```json theme={null}
{
"model": "skyreels-v4-fast",
"prompt": "@Actor-1 walks through a neon-lit street at night.",
"ref_images": [
{ "tag": "@Actor-1", "type": "image", "image_urls": ["https://example.com/actor.jpg"] }
]
}
```
### Case 6: Omni - Multi-Subject + Video Motion Reference
```json theme={null}
{
"model": "skyreels-v4-fast",
"prompt": "The man from @image_1 imitates the move on the left in @video_1. The woman from @image_2 imitates the right side.",
"duration": 5,
"ref_images": [
{ "tag": "@image_1", "type": "image", "image_urls": ["https://example.com/a.png"] },
{ "tag": "@image_2", "type": "image", "image_urls": ["https://example.com/b.png"] }
],
"ref_videos": [
{ "tag": "@video_1", "type": "reference", "video_url": "https://example.com/motion.mp4" }
]
}
```
This case uses `ref_videos.type=reference`, so **the requested `duration` will be overridden by the actual reference video length** (max 10 seconds). Even though `"duration": 5` is passed here, the final video length follows the reference video.
### Case 7: Omni - Grid Collage
```json theme={null}
{
"model": "skyreels-v4-fast",
"prompt": "Create a video showing how to make tomato and egg noodles based on @image1.",
"ref_images": [
{ "tag": "@image1", "type": "grid", "image_urls": ["https://example.com/recipe_grid.png"] }
]
}
```
### Case 8: Omni - Video Extension (extend)
```json theme={null}
{
"model": "skyreels-v4-fast",
"prompt": "Video extended @video1, someone walks over and sits on the sofa.",
"duration": 8,
"ref_videos": [
{ "tag": "@video1", "type": "extend", "video_url": "https://example.com/source.mp4" }
]
}
```
### Case 9: Omni - Audio Sync (Voice-Driven)
```json theme={null}
{
"model": "skyreels-v4-std",
"prompt": "@Actor-1 speaks with a calm tone.",
"ref_images": [
{
"tag": "@Actor-1",
"type": "image",
"image_urls": ["https://example.com/actor.jpg"],
"audio_url": "https://example.com/voice.mp3"
}
]
}
```
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Sora2 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/sora-2/generation
POST https://api.apimart.ai/v1/videos/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Supports multiple generation modes including text-to-video and image-to-video
- Supports both `sora-2` and `sora-2-pro` models
- Generated video links are valid for 24 hours, please save them promptly
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "sora-2",
"prompt": "A waterfall cascading down forming a rainbow",
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png"]
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "sora-2",
"prompt": "A waterfall cascading down forming a rainbow",
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png"]
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "sora-2",
prompt: "A waterfall cascading down forming a rainbow",
duration: 8,
resolution: "720p",
aspect_ratio: "16:9",
image_urls: [
"https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png",
],
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "sora-2",
"prompt": "A waterfall cascading down forming a rainbow",
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9",
"image_urls": []string{"https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png"},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "sora-2",
"prompt": "A waterfall cascading down forming a rainbow",
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png"]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"sora-2",
"prompt" => "A waterfall cascading down forming a rainbow",
"duration" => 8,
"resolution" => "720p",
"aspect_ratio" => "16:9",
"image_urls" => ["https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png"]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "sora-2",
prompt: "A waterfall cascading down forming a rainbow",
duration: 8,
resolution: "720p",
aspect_ratio: "16:9",
image_urls: ["https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png"]
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "sora-2",
"prompt": "A waterfall cascading down forming a rainbow",
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png"]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""sora-2"",
""prompt"": ""A waterfall cascading down forming a rainbow"",
""duration"": 8,
""resolution"": ""720p"",
""aspect_ratio"": ""16:9"",
""image_urls"": [""https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png""]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/videos/generations";
const char *payload = "{"
"\"model\":\"sora-2\","
"\"prompt\":\"A waterfall cascading down forming a rainbow\","
"\"duration\":8,"
"\"resolution\":\"720p\","
"\"aspect_ratio\":\"16:9\","
"\"image_urls\":[\"https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png\"]"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/videos/generations"];
NSDictionary *payload = @{
@"model": @"sora-2",
@"prompt": @"A waterfall cascading down forming a rainbow",
@"duration": @8,
@"resolution": @"720p",
@"aspect_ratio": @"16:9",
@"image_urls": @[@"https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png"]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/videos/generations"
let payload = {|{
"model": "sora-2",
"prompt": "A waterfall cascading down forming a rainbow",
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png"]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/videos/generations');
final payload = {
'model': 'sora-2',
'prompt': 'A waterfall cascading down forming a rainbow',
'duration': 8,
'resolution': '720p',
'aspect_ratio': '16:9',
'image_urls': ['https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png']
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/videos/generations"
payload <- list(
model = "sora-2",
prompt = "A waterfall cascading down forming a rainbow",
duration = 8,
resolution = "720p",
aspect_ratio = "16:9",
image_urls = c("https://cdn.apimart.ai/doc/9998238782946594-f62f70ce-348c-4b13-bb5f-15f17bee676b-image_task_01K88BEGZHVJWJ3ZV6HY99SWQR_0.png")
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Video generation model name
Supported models:
* `sora-2` Sora 2 standard
* `sora-2-pro` Sora 2 Pro
Example: `"sora-2"`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for video generation
Example: `"A waterfall cascading down forming a rainbow"`
Supported values: `4`, `8`, `12`, `16`, `20`
Example: `8`
Video resolution
Supported values:
| Model | Allowed values |
| ------------ | ------------------------ |
| `sora-2` | `720p` |
| `sora-2-pro` | `720p`, `1024p`, `1080p` |
Defaults to `720p` when not provided.
Example: `"720p"`
Video aspect ratio, controls landscape or portrait orientation
Supported values:
| Orientation | Allowed values |
| ----------- | ------------------- |
| Landscape | `16:9`, `landscape` |
| Portrait | `9:16`, `portrait` |
Defaults to landscape when not provided.
When `image_urls` is provided (image-to-video), the `aspect_ratio` parameter is ignored and does not need to be sent; the orientation is determined automatically from the reference image.
Array of reference image URLs for image-to-video generation
* Omit for text-to-video; provide 1 image for image-to-video
* **Maximum 1 image**
* Supports publicly accessible image URLs (http\:// or https\://)
* Supported formats: `.jpeg`, `.jpg`, `.png`, `.webp`
* Maximum file size: 10MB
Example: `["https://example.com/image.jpg"]`
## Response
Response status code, 200 for success
Response data array
Task status, `submitted` upon initial submission
Unique task identifier for querying task status and results
# VEO3 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/veo3/generation
POST https://api.apimart.ai/v1/videos/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Supports multiple generation modes including text-to-video and image-to-video
- Supports **4K** resolution output
- Generated video links are valid for 24 hours, please save them promptly
**Model name compatibility note**: This endpoint also accepts the aliases `veo3.1-fast-ext` (equivalent to `veo3.1-fast`), `veo3.1-quality-ext` (equivalent to `veo3.1-quality`), and `veo3.1-lite-ext` (equivalent to `veo3.1-lite`). Each alias is interchangeable with its model and produces identical results.
```bash cURL theme={null}
# model can be "veo3.1-fast", or the compatible alias "veo3.1-fast-ext"
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "veo3.1-fast",
"prompt": "Dolphins leaping in the azure ocean",
"duration": 8,
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png"]
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "veo3.1-fast",
"prompt": "Dolphins leaping in the azure ocean",
"duration": 8,
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png"]
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "veo3.1-fast",
prompt: "Dolphins leaping in the azure ocean",
duration: 8,
aspect_ratio: "16:9",
image_urls: ["https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png"]
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "veo3.1-fast",
"prompt": "Dolphins leaping in the azure ocean",
"duration": 8,
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png"],
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "veo3.1-fast",
"prompt": "Dolphins leaping in the azure ocean",
"duration": 8,
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png"]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"veo3.1-fast",
"prompt" => "Dolphins leaping in the azure ocean",
"duration" => 8,
"aspect_ratio" => "16:9",
"image_urls" => ["https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png"]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "veo3.1-fast",
prompt: "Dolphins leaping in the azure ocean",
duration: 8,
aspect_ratio: "16:9",
image_urls: ["https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png"]
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "veo3.1-fast",
"prompt": "Dolphins leaping in the azure ocean",
"duration": 8,
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png"]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""veo3.1-fast"",
""prompt"": ""Dolphins leaping in the azure ocean"",
""duration"": 8,
""aspect_ratio"": ""16:9"",
""image_urls"": [""https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png""]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/videos/generations";
const char *payload = "{"
"\"model\":\"veo3.1-fast\","
"\"prompt\":\"Dolphins leaping in the azure ocean\","
"\"duration\":8,"
"\"aspect_ratio\":\"16:9\","
"\"image_urls\":[\"https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png\"]"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/videos/generations"];
NSDictionary *payload = @{
@"model": @"veo3.1-fast",
@"prompt": @"Dolphins leaping in the azure ocean",
@"duration": @8,
@"aspect_ratio": @"16:9",
@"image_urls": @[@"https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png"]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/videos/generations"
let payload = {|{
"model": "veo3.1-fast",
"prompt": "Dolphins leaping in the azure ocean",
"duration": 8,
"aspect_ratio": "16:9",
"image_urls": ["https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png"]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/videos/generations');
final payload = {
'model': 'veo3.1-fast',
'prompt': 'Dolphins leaping in the azure ocean',
'duration': 8,
'aspect_ratio': '16:9',
'image_urls': ['https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png']
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/videos/generations"
payload <- list(
model = "veo3.1-fast",
prompt = "Dolphins leaping in the azure ocean",
duration = 8,
aspect_ratio = "16:9",
image_urls = c("https://cdn.apimart.ai/doc/9998238783208208-9972597b-255d-4e7e-9649-e6ee38a837aa-image_task_01K88B53MTK41PP5KGDTG2PA5P_0.png")
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Available models:
* `veo3.1-fast` - Fast generation model, suitable for quick previews and iterations (compatible alias `veo3.1-fast-ext`)
* `veo3.1-quality` - High quality generation model, suitable for final production (compatible alias `veo3.1-quality-ext`)
* `veo3.1-lite` - Lightweight generation model, suitable for low-cost batch generation (compatible alias `veo3.1-lite-ext`)
Example: `"veo3.1-fast"`
For backward compatibility, the aliases `veo3.1-fast-ext` (for `veo3.1-fast`), `veo3.1-quality-ext` (for `veo3.1-quality`) and `veo3.1-lite-ext` (for `veo3.1-lite`) remain usable.
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description for video generation
Video duration in seconds
Fixed value: `8` (VEO3 only supports 8 seconds duration)
Video aspect ratio
Supported formats:
* `16:9` (Landscape)
* `9:16` (Portrait)
Video generation type
Supported types:
* `frame` - Frame-to-video (FL mode)
* `reference` - Reference image-to-video
If not specified, defaults based on image count: 2 images for frame-to-video, 3 images for reference image-to-video
**Note: `veo3.1-quality` model does not support `reference` mode**
`veo3.1-lite` model does not support this parameter, do not pass it
Array of reference image URLs for image-to-video generation
Supports publicly accessible image URLs (http\:// or https\://)
Example: `["https://example.com/image.jpg"]`
**Limitations:**
* Maximum 3 images
* For frame-to-video mode: first image is the start frame, second image is the end frame
* Maximum file size: 10MB
* Supported formats: .jpeg, .jpg, .png, .webp
`veo3.1-lite` model does not support this parameter, do not pass it
Video resolution
Supported values:
* `720p` (Default)
* `1080p`
* `4k`
Enable GIF output format. Default: false
Note: GIF and 1080p/4k resolution cannot be used simultaneously
Whether to use official channel as fallback
* `false`: Do not use (default)
* `true`: Use official channel
`veo3.1-lite` model does not support this parameter, do not pass it
## Response
Response status code
Response data array
Task status
* `submitted` - Submitted
Unique task identifier
# VEO3 Official Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/veo3/generation-official
POST https://api.apimart.ai/v1/videos/generations
- Asynchronous processing mode, returns task ID for subsequent queries
- Supports text-to-video and image-to-video (first frame / first & last frame control)
- Supports 720P and 1080P resolution
- Supports 4/6/8 second video duration
- Supports audio track generation
- Supports person generation policy control
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "veo3.1-fast-official",
"prompt": "a golden retriever running on the beach, sunset, cinematic",
"duration": 8,
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "veo3.1-fast-official",
"prompt": "a golden retriever running on the beach, sunset, cinematic",
"duration": 8,
"aspect_ratio": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "veo3.1-fast-official",
prompt: "a golden retriever running on the beach, sunset, cinematic",
duration: 8,
aspect_ratio: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "veo3.1-fast-official",
"prompt": "a golden retriever running on the beach, sunset, cinematic",
"duration": 8,
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "veo3.1-fast-official",
"prompt": "a golden retriever running on the beach, sunset, cinematic",
"duration": 8,
"aspect_ratio": "16:9"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"veo3.1-fast-official",
"prompt" => "a golden retriever running on the beach, sunset, cinematic",
"duration" => 8,
"aspect_ratio" => "16:9"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "veo3.1-fast-official",
prompt: "a golden retriever running on the beach, sunset, cinematic",
duration: 8,
aspect_ratio: "16:9"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "veo3.1-fast-official",
"prompt": "a golden retriever running on the beach, sunset, cinematic",
"duration": 8,
"aspect_ratio": "16:9"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""veo3.1-fast-official"",
""prompt"": ""a golden retriever running on the beach, sunset, cinematic"",
""duration"": 8,
""aspect_ratio"": ""16:9""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_xxxxxxxxxx"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please recharge and try again",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Available models:
* `veo3.1-fast-official` - Veo 3.1 Official Fast version
* `veo3.1-quality-official` - Veo 3.1 Official High Quality version
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Positive text prompt
Describe scenes, actions, styles, etc. in detail for better generation results. English prompts are recommended.
Example: `"a golden retriever running on the beach, sunset, cinematic"`
Negative prompt to exclude unwanted content
Example: `"blurry, low quality, watermark, text"`
Video duration in seconds
Recommended values: `4` / `6` / `8`
Default: `8`
**Note:** Must be a pure number (e.g. `8`), do not add quotes, otherwise an error will occur
Video aspect ratio
Available values:
* `16:9` - Landscape
* `9:16` - Portrait
Default: `16:9`
Video resolution
Available values:
* `720p` - Standard resolution
* `1080p` - High definition
* `4K` - Ultra high definition
Default: `720p`
First frame image URL for image-to-video generation
* Image URL must be publicly accessible without hotlink protection
* Object storage URLs are recommended over temporary download links
Last frame image URL for image-to-video generation
Used with `first_frame_image` to control first and last frames
Random seed for reproducing generation results
Value range: `0` - `4294967295`
Number of samples to generate (1-4), currently recommended to use `1`
Default: `1`
Whether to generate audio track
Person generation policy
Available values:
* `allow_adult` - Only allow generating adult persons/faces
* `disallow` - Do not allow generating persons or faces
Default: `allow_adult`
Image resize strategy (effective for image-to-video)
Available values:
* `pad` - Padding mode
* `crop` - Cropping mode
Default: `pad`
Whether to enable upstream prompt enhancement
Default: `true`
* This parameter can only be set to `true`. Setting it to `false` will cause a request error
* If you don't need this parameter, do not include it
## Text-to-Video vs Image-to-Video
The system automatically determines the mode based on whether image parameters are provided: no images for text-to-video, images for image-to-video.
| Parameter | Text-to-Video | Image-to-Video |
| ------------------- | -------------- | ----------------------- |
| `prompt` | Required | Required |
| `first_frame_image` | Not used | Required (at least one) |
| `last_frame_image` | Not used | Optional (last frame) |
| `negative_prompt` | Optional | Optional |
| `duration` | Optional | Optional |
| `aspect_ratio` | Optional | Optional |
| `resolution` | Optional | Optional |
| `seed` | Optional | Optional |
| `generate_audio` | Optional | Optional |
| `person_generation` | Optional | Optional |
| `resize_mode` | Not applicable | Optional |
| `enhance_prompt` | Optional | Optional |
## Response
Response status code, 200 on success
Response data array
Task status, initially `submitted` upon submission
Unique task identifier for querying task status and results
## Usage Scenarios
### Scenario 1: Text-to-Video (Basic)
```json theme={null}
{
"model": "veo3.1-fast-official",
"prompt": "a golden retriever running on the beach, sunset, cinematic"
}
```
### Scenario 2: Text-to-Video (Full Parameters)
```json theme={null}
{
"model": "veo3.1-quality-official",
"prompt": "a cinematic close-up of a ragdoll cat slowly walking through a sunlit living room",
"negative_prompt": "blurry, low quality, watermark, text",
"duration": 8,
"aspect_ratio": "16:9",
"resolution": "1080p",
"seed": 12345,
"generate_audio": true,
"person_generation": "disallow",
"enhance_prompt": true
}
```
### Scenario 3: Image-to-Video (Single First Frame)
```json theme={null}
{
"model": "veo3.1-fast-official",
"prompt": "the cat slowly walks forward and looks around",
"first_frame_image": "https://example.com/cat.png",
"duration": 8,
"resolution": "720p"
}
```
### Scenario 4: Image-to-Video (First Frame + Last Frame)
```json theme={null}
{
"model": "veo3.1-quality-official",
"prompt": "smooth cinematic transition from the first frame to the last frame",
"first_frame_image": "https://example.com/frame-start.png",
"last_frame_image": "https://example.com/frame-end.png",
"duration": 8,
"resolution": "1080p"
}
```
### Scenario 5: Video with Audio
```json theme={null}
{
"model": "veo3.1-quality-official",
"prompt": "a busy coffee shop with people chatting and barista making latte art",
"duration": 8,
"generate_audio": true,
"aspect_ratio": "16:9"
}
```
**Query Task Results**
Video generation is an asynchronous task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# VEO3 Video Remix
Source: https://docs.apimart.ai/en/api-reference/videos/veo3/remix
POST https://api.apimart.ai/v1/videos/{task_id}/remix
- Extend generated videos by continuing from 8 seconds to 15 seconds
- Asynchronous processing mode, returns task ID for subsequent queries
- Generated video links are valid for 24 hours, please save them promptly
**Model name compatibility note**: This endpoint also accepts the aliases `veo3.1-fast-ext` (equivalent to `veo3.1-fast`) and `veo3.1-quality-ext` (equivalent to `veo3.1-quality`). Each alias is interchangeable with its model and produces identical results.
```bash cURL theme={null}
# model can be "veo3.1-fast", or the compatible alias "veo3.1-fast-ext"
curl --request POST \
--url https://api.apimart.ai/v1/videos/{task_id}/remix \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "veo3.1-fast",
"prompt": "The cat continues running on the grass, butterflies fly into the distance",
"raw": false,
"aspect_ratio": "16:9",
"resolution": "720p"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/{task_id}/remix"
payload = {
"model": "veo3.1-fast",
"prompt": "The cat continues running on the grass, butterflies fly into the distance",
"raw": False,
"aspect_ratio": "16:9",
"resolution": "720p"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/{task_id}/remix";
const payload = {
model: "veo3.1-fast",
prompt: "The cat continues running on the grass, butterflies fly into the distance",
raw: false,
aspect_ratio: "16:9",
resolution: "720p"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/{task_id}/remix"
payload := map[string]interface{}{
"model": "veo3.1-fast",
"prompt": "The cat continues running on the grass, butterflies fly into the distance",
"raw": false,
"aspect_ratio": "16:9",
"resolution": "720p",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/{task_id}/remix";
String payload = """
{
"model": "veo3.1-fast",
"prompt": "The cat continues running on the grass, butterflies fly into the distance",
"raw": false,
"aspect_ratio": "16:9",
"resolution": "720p"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"veo3.1-fast",
"prompt" => "The cat continues running on the grass, butterflies fly into the distance",
"raw" => false,
"aspect_ratio" => "16:9",
"resolution" => "720p"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/{task_id}/remix")
payload = {
model: "veo3.1-fast",
prompt: "The cat continues running on the grass, butterflies fly into the distance",
raw: false,
aspect_ratio: "16:9",
resolution: "720p"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/{task_id}/remix")!
let payload: [String: Any] = [
"model": "veo3.1-fast",
"prompt": "The cat continues running on the grass, butterflies fly into the distance",
"raw": false,
"aspect_ratio": "16:9",
"resolution": "720p"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/{task_id}/remix";
var payload = @"{
""model"": ""veo3.1-fast"",
""prompt"": ""The cat continues running on the grass, butterflies fly into the distance"",
""raw"": false,
""aspect_ratio"": ""16:9"",
""resolution"": ""720p""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/videos/{task_id}/remix";
const char *payload = "{"
"\"model\":\"veo3.1-fast\","
"\"prompt\":\"The cat continues running on the grass, butterflies fly into the distance\","
"\"raw\":false,"
"\"aspect_ratio\":\"16:9\","
"\"resolution\":\"720p\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/videos/{task_id}/remix"];
NSDictionary *payload = @{
@"model": @"veo3.1-fast",
@"prompt": @"The cat continues running on the grass, butterflies fly into the distance",
@"raw": @NO,
@"aspect_ratio": @"16:9",
@"resolution": @"720p"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/videos/{task_id}/remix"
let payload = {|{
"model": "veo3.1-fast",
"prompt": "The cat continues running on the grass, butterflies fly into the distance",
"raw": false,
"aspect_ratio": "16:9",
"resolution": "720p"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/videos/{task_id}/remix');
final payload = {
'model': 'veo3.1-fast',
'prompt': 'The cat continues running on the grass, butterflies fly into the distance',
'raw': false,
'aspect_ratio': '16:9',
'resolution': '720p'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/videos/{task_id}/remix"
payload <- list(
model = "veo3.1-fast",
prompt = "The cat continues running on the grass, butterflies fly into the distance",
raw = FALSE,
aspect_ratio = "16:9",
resolution = "720p"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JQXYZ9999NEWEXTENDID"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 404 theme={null}
{
"error": {
"code": 404,
"message": "Video not found",
"type": "not_found_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Path Parameters
Original video task ID
This is the task\_id returned from the video generation API. The original video task status must be `success`
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video model name, must match the model used for the original video
Supported models:
* `veo3.1-fast` - Fast version (compatible alias `veo3.1-fast-ext`)
* `veo3.1-quality` - High quality version (compatible alias `veo3.1-quality-ext`)
Example: `"veo3.1-fast"`
For backward compatibility, the aliases `veo3.1-fast-ext` (for `veo3.1-fast`) and `veo3.1-quality-ext` (for `veo3.1-quality`) remain usable.
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Continuation prompt describing the content for the extended portion
Whether to return only the extended portion of the video
* `true` - Only returns the extended video
Default: `false`
Aspect ratio for the extended video
Supported values:
* `16:9`
* `9:16`
Video resolution
Supported values:
* `720p` (default)
* `1080p`
* `4k`
## Important Notes
**Model must match**: The model used for extension must be the same as the one used to generate the original video. Videos generated with `veo3.1-fast` must also use `veo3.1-fast` for extension.
**Only completed videos supported**: The original video task status must be `success`.
**task\_id in URL**: This is the `task_id` returned from the first step of video generation (not the upstream ID).
## Response
Response status code
Response data array
New task ID for querying the extended video status
Task status
Possible values:
* `submitted` - Submitted
# Vidu Q3(pro/turbo) Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/vidu-q3-pro/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns task ID for subsequent queries
- Supports text-to-video, image-to-video, first-last frame video generation
- Supports 540p / 720p / 1080p resolution
- Duration range 1-16 seconds, audio enabled by default
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "viduq3-pro",
"prompt": "A cat playing piano, camera slowly zooms in",
"duration": 8,
"resolution": "1080p",
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "viduq3-pro",
"prompt": "A cat playing piano, camera slowly zooms in",
"duration": 8,
"resolution": "1080p",
"aspect_ratio": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "viduq3-pro",
prompt: "A cat playing piano, camera slowly zooms in",
duration: 8,
resolution: "1080p",
aspect_ratio: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "viduq3-pro",
"prompt": "A cat playing piano, camera slowly zooms in",
"duration": 8,
"resolution": "1080p",
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "viduq3-pro",
"prompt": "A cat playing piano, camera slowly zooms in",
"duration": 8,
"resolution": "1080p",
"aspect_ratio": "16:9"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"viduq3-pro",
"prompt" => "A cat playing piano, camera slowly zooms in",
"duration" => 8,
"resolution" => "1080p",
"aspect_ratio" => "16:9"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "viduq3-pro",
prompt: "A cat playing piano, camera slowly zooms in",
duration: 8,
resolution: "1080p",
aspect_ratio: "16:9"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "viduq3-pro",
"prompt": "A cat playing piano, camera slowly zooms in",
"duration": 8,
"resolution": "1080p",
"aspect_ratio": "16:9"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""viduq3-pro"",
""prompt"": ""A cat playing piano, camera slowly zooms in"",
""duration"": 8,
""resolution"": ""1080p"",
""aspect_ratio"": ""16:9""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_xxxxxxxxxx"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `viduq3-pro` - Vidu Q3 Pro
* `viduq3-turbo` - Vidu Q3 Turbo
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text prompt, maximum **2000 characters**
Required for text-to-video. Optional for image-to-video and first-last frame modes.
Example: `"A cat playing piano, camera slowly zooms in"`
Video duration (seconds)
Range: `1` to `16`
Default: `5`
Video resolution
Options:
* `540p` - Standard definition
* `720p` - HD (default)
* `1080p` - Full HD
Default: `720p`
Video aspect ratio (only for text-to-video mode)
Options:
* `16:9` - Landscape
* `9:16` - Portrait
* `4:3` - Traditional
* `3:4` - Portrait traditional
* `1:1` - Square
This parameter is only available in text-to-video mode (when `image_urls` is not provided).
Image URL array for image-to-video generation
The system automatically determines the generation mode based on the number of images:
* **0 images** (not provided): Text-to-video mode
* **1 image**: Image-to-video mode (image used as starting frame)
* **2 images**: First-last frame mode (first image = first frame, second image = last frame)
Example: `["https://example.com/photo.jpg"]`
* Maximum 2 images supported
* For first-last frame mode, exactly 2 images must be provided
* When `image_urls` is provided (whether 1 or 2 images), the `aspect_ratio` parameter cannot be used — the video aspect ratio will be automatically determined by the image
Whether to generate audio (dialogue, sound effects)
Default: `true`
Set to `false` if you need a silent video.
Seed integer used to control randomness in generated content
Range: integer between `-1` and `2^32-1`
* With the same request, different seed values (including unspecified or `-1`, which uses a random number instead) will produce different results
* With the same request, the same seed value will produce similar results, but exact reproducibility is not guaranteed
## Auto Routing
The system automatically determines the generation mode based on the number of images in `image_urls`:
| Images Count | Mode | Description |
| ---------------- | ---------------- | ---------------------------------------------------- |
| 0 (not provided) | Text-to-Video | Generate from text description only |
| 1 | Image-to-Video | Use the image as starting frame |
| 2 | First-Last Frame | First image = first frame, second image = last frame |
## Parameter Support Matrix
| Parameter | Text-to-Video | Image-to-Video | First-Last Frame |
| -------------- | ------------- | -------------- | ---------------- |
| `model` | ✅ Required | ✅ Required | ✅ Required |
| `prompt` | ✅ Required | Optional | Optional |
| `image_urls` | - | ✅ 1 image | ✅ 2 images |
| `duration` | ✅ 1-16s | ✅ 1-16s | ✅ 1-16s |
| `resolution` | ✅ | ✅ | ✅ |
| `aspect_ratio` | ✅ | - | - |
| `audio` | ✅ | ✅ | ✅ |
| `seed` | ✅ | ✅ | ✅ |
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video
```json theme={null}
{
"model": "viduq3-pro",
"prompt": "A cat playing piano, camera slowly zooms in",
"duration": 8,
"resolution": "1080p",
"aspect_ratio": "16:9"
}
```
### Case 2: Image-to-Video (Single Image)
```json theme={null}
{
"model": "viduq3-pro",
"prompt": "The person slowly turns and smiles",
"image_urls": ["https://example.com/photo.jpg"],
"duration": 5,
"resolution": "720p"
}
```
### Case 3: First-Last Frame Video
```json theme={null}
{
"model": "viduq3-pro",
"prompt": "The person gradually sits down from standing",
"image_urls": [
"https://example.com/first.jpg",
"https://example.com/last.jpg"
],
"duration": 8
}
```
### Case 4: Silent Video (Audio Disabled)
```json theme={null}
{
"model": "viduq3-pro",
"prompt": "Sunset seascape timelapse photography",
"duration": 10,
"resolution": "1080p",
"audio": false
}
```
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Vidu Q3(mix/standard) Reference-to-Video
Source: https://docs.apimart.ai/en/api-reference/videos/vidu-q3/generation
POST https://api.apimart.ai/v1/videos/generations
- Async processing mode, returns task ID for subsequent queries
- Upload 1-7 reference images + text prompt to generate short videos containing reference subjects
- Supports 540p / 720p / 1080p resolution
- Duration range 1-16 seconds, suitable for character consistency and style continuation
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "viduq3",
"prompt": "Santa Claus and the bear hug by the lakeside",
"image_urls": [
"https://example.com/santa.png",
"https://example.com/bear.png"
],
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "viduq3",
"prompt": "Santa Claus and the bear hug by the lakeside",
"image_urls": [
"https://example.com/santa.png",
"https://example.com/bear.png"
],
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "viduq3",
prompt: "Santa Claus and the bear hug by the lakeside",
image_urls: [
"https://example.com/santa.png",
"https://example.com/bear.png"
],
duration: 8,
resolution: "720p",
aspect_ratio: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "viduq3",
"prompt": "Santa Claus and the bear hug by the lakeside",
"image_urls": []string{"https://example.com/santa.png", "https://example.com/bear.png"},
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "viduq3",
"prompt": "Santa Claus and the bear hug by the lakeside",
"image_urls": [
"https://example.com/santa.png",
"https://example.com/bear.png"
],
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"viduq3",
"prompt" => "Santa Claus and the bear hug by the lakeside",
"image_urls" => [
"https://example.com/santa.png",
"https://example.com/bear.png"
],
"duration" => 8,
"resolution" => "720p",
"aspect_ratio" => "16:9"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "viduq3",
prompt: "Santa Claus and the bear hug by the lakeside",
image_urls: [
"https://example.com/santa.png",
"https://example.com/bear.png"
],
duration: 8,
resolution: "720p",
aspect_ratio: "16:9"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "viduq3",
"prompt": "Santa Claus and the bear hug by the lakeside",
"image_urls": [
"https://example.com/santa.png",
"https://example.com/bear.png"
],
"duration": 8,
"resolution": "720p",
"aspect_ratio": "16:9"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""viduq3"",
""prompt"": ""Santa Claus and the bear hug by the lakeside"",
""image_urls"": [
""https://example.com/santa.png"",
""https://example.com/bear.png""
],
""duration"": 8,
""resolution"": ""720p"",
""aspect_ratio"": ""16:9""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_xxxxxxxxxx"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name
Supported models:
* `viduq3-mix` - Premium quality, stronger smart transitions, supports 1-second short videos
* `viduq3` - Default choice, smarter camera switching
**How to choose**: Use `viduq3` for everyday use; use `viduq3-mix` for premium quality or 1-2 second motion effects.
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text prompt, maximum **5000 characters**
Describe actions and camera movements, not appearance (appearance is determined by reference images).
Example: `"Santa Claus and the bear hug by the lakeside"`
Reference image URL array, **1-7 images**
Supports publicly accessible image URLs (http\:// or https\://)
Example: `["https://example.com/santa.png", "https://example.com/bear.png"]`
* Quantity: **1-7 images**
* Supported formats: PNG, JPEG, JPG, WebP
* Minimum size: 128×128
* Aspect ratio: between 1:4 and 4:1
* Maximum file size: ≤ 50MB per image
* Must be publicly accessible URLs
Video duration (seconds)
* `viduq3-mix`: `1` to `16`
* `viduq3`: `3` to `16`
Default: `5`
`viduq3` supports minimum 3 seconds, `viduq3-mix` supports minimum 1 second. Please pass a valid duration based on the selected model.
Video resolution
* `viduq3-mix`: `720p` (default) / `1080p`
* `viduq3`: `540p` / `720p` (default) / `1080p`
`viduq3-mix` does not support `540p`, please use `720p` or `1080p`.
Video aspect ratio
Options:
* `16:9` - Landscape (default)
* `9:16` - Portrait
* `4:3` - Traditional
* `3:4` - Portrait traditional
* `1:1` - Square
Random seed for controlling generation randomness
If not provided, a random seed will be used.
Using the same seed with identical parameters will produce similar results, but not guaranteed to be exactly the same.
## Model Comparison
| Feature | `viduq3` | `viduq3-mix` |
| ---------------- | ------------------------------------------ | ------------------------------------------ |
| Recommended for | Everyday use, multi-angle camera switching | Premium quality, 1-2 second motion effects |
| Duration range | 3-16 seconds | 1-16 seconds |
| Resolution | 540p / 720p / 1080p | 720p / 1080p |
| Reference images | 1-7 images | 1-7 images |
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: viduq3 Basic Reference-to-Video
```json theme={null}
{
"model": "viduq3",
"prompt": "Santa Claus and the bear hug by the lakeside",
"image_urls": [
"https://example.com/santa.png",
"https://example.com/bear.png"
]
}
```
### Case 2: viduq3-mix High Quality Reference-to-Video
```json theme={null}
{
"model": "viduq3-mix",
"prompt": "A cyberpunk neon street with the cat from reference image walking by",
"image_urls": [
"https://example.com/cat-1.png",
"https://example.com/cat-2.png",
"https://example.com/cat-3.png"
],
"duration": 8,
"resolution": "1080p",
"aspect_ratio": "16:9",
"seed": 42
}
```
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# wan2.5-preview Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/wan2.5/generation
POST https://api.apimart.ai/v1/videos/generations
- Wanxiang 2.5 preview video generation model
- Supports Text-to-Video and Image-to-Video
- Supports 480p/720p/1080p resolution, 5 or 10 seconds duration
- Supports auto prompt extension, auto audio and custom audio
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.5-preview",
"prompt": "Sunset coastal highway, cinematic shot",
"size": "16:9",
"resolution": "720p",
"duration": 5
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan2.5-preview",
"prompt": "Sunset coastal highway, cinematic shot",
"size": "16:9",
"resolution": "720p",
"duration": 5
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan2.5-preview",
prompt: "Sunset coastal highway, cinematic shot",
size: "16:9",
resolution: "720p",
duration: 5
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan2.5-preview",
"prompt": "Sunset coastal highway, cinematic shot",
"size": "16:9",
"resolution": "720p",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "wan2.5-preview",
"prompt": "Sunset coastal highway, cinematic shot",
"size": "16:9",
"resolution": "720p",
"duration": 5
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"wan2.5-preview",
"prompt" => "Sunset coastal highway, cinematic shot",
"size" => "16:9",
"resolution" => "720p",
"duration" => 5
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "wan2.5-preview",
prompt: "Sunset coastal highway, cinematic shot",
size: "16:9",
resolution: "720p",
duration: 5
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "wan2.5-preview",
"prompt": "Sunset coastal highway, cinematic shot",
"size": "16:9",
"resolution": "720p",
"duration": 5
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""wan2.5-preview"",
""prompt"": ""Sunset coastal highway, cinematic shot"",
""size"": ""16:9"",
""resolution"": ""720p"",
""duration"": 5
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance, please top up",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name, fixed as `wan2.5-preview`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description
**Required** for text-to-video (without `image_urls`), optional but recommended for image-to-video
Describe scenes, actions, styles in detail for better results
Example: `"Sunset coastal highway, cinematic shot"`
Reference image URL array (only 1 image supported)
Required for image-to-video mode, supports publicly accessible image URLs or Base64 encoding (`data:image/png;base64,...`)
Example: `["https://example.com/image.jpg"]`
The system automatically selects text-to-video or image-to-video mode based on whether `image_urls` is included. **Do not** pass `image_urls` for text-to-video mode.
Negative prompt, describes unwanted content
Maximum 500 characters
Example: `"blurry, low quality, distorted"`
Video resolution
Options:
* `480p` - SD, supports size: `16:9`, `9:16`, `1:1`
* `720p` - HD (default), supports size: `16:9`, `9:16`, `1:1`, `4:3`, `3:4`
* `1080p` - FHD, supports size: `16:9`, `9:16`, `1:1`, `4:3`, `3:4`
Default: `720p`
Resolution directly affects pricing: 1080p > 720p > 480p.
480p only supports `16:9`, `9:16`, `1:1` ratios. Passing `4:3` or `3:4` will result in an error.
Video duration (seconds)
Only supports: `5` or `10` seconds
Default: `5`
Aspect ratio, **only effective for text-to-video** (without `image_urls`)
Options depend on `resolution`:
**480p:**
* `16:9` - Landscape (default)
* `9:16` - Portrait
* `1:1` - Square
**720p / 1080p:**
* `16:9` - Landscape (default)
* `9:16` - Portrait
* `1:1` - Square
* `4:3` - Landscape
* `3:4` - Portrait
Default: `16:9`
For image-to-video, the aspect ratio is determined by the input image. **Do not** pass `size`, otherwise an error will be returned.
Random seed (≥0), specifying the same seed can reproduce similar results
Example: `12345`
Whether to enable smart prompt rewriting
Significantly improves results for shorter prompts, but increases processing time
Default: `true`
Whether to automatically add audio
When enabled, the system will generate matching audio for the video
Default: `true`
This model only supports `audio=true`. Setting to `false` for silent video is not supported.
Custom audio URL (wav/mp3, 3-30 seconds, ≤ 15MB)
If the audio is longer than the video duration, it will be automatically trimmed; if shorter, the remaining part will be silent
Audio file requirements:
* Format: wav, mp3
* Duration: 3-30 seconds
* Size: ≤ 15MB
Whether to add an "AI Generated" watermark (bottom right)
Default: `false`
## Resolution and Aspect Ratio Combinations
`size` and `resolution` combinations map to upstream pixel dimensions (**only effective for text-to-video**):
| Aspect Ratio | Description | 480p Size | 720p Size | 1080p Size |
| ------------ | ------------------- | --------- | --------- | ---------- |
| `16:9` | Landscape (default) | 832×480 | 1280×720 | 1920×1080 |
| `9:16` | Portrait | 480×832 | 720×1280 | 1080×1920 |
| `1:1` | Square | 624×624 | 960×960 | 1440×1440 |
| `4:3` | Landscape | - | 1088×832 | 1632×1248 |
| `3:4` | Portrait | - | 832×1088 | 1248×1632 |
480p only supports `16:9`, `9:16`, `1:1` ratios. Passing `4:3` or `3:4` will result in an error. 720p and 1080p support all 5 ratios.
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` on initial submission
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video (Simple)
```json theme={null}
{
"model": "wan2.5-preview",
"prompt": "Sunset coastal highway, cinematic shot"
}
```
### Case 2: Text-to-Video (Full Parameters)
```json theme={null}
{
"model": "wan2.5-preview",
"prompt": "City night scene, neon lights and rain-soaked streets",
"negative_prompt": "blurry, low quality, distorted",
"size": "16:9",
"resolution": "720p",
"duration": 5,
"seed": 12345,
"prompt_extend": true,
"audio": true,
"watermark": false
}
```
### Case 3: Image-to-Video
```json theme={null}
{
"model": "wan2.5-preview",
"prompt": "Cat running on the grass",
"image_urls": ["https://example.com/cat.jpg"],
"resolution": "480p",
"duration": 5
}
```
### Case 4: Image-to-Video (Base64 Image)
```json theme={null}
{
"model": "wan2.5-preview",
"prompt": "Make the cat stand up and walk",
"image_urls": ["data:image/png;base64,iVBORw0KGgo..."],
"duration": 5
}
```
### Case 5: Custom Audio
```json theme={null}
{
"model": "wan2.5-preview",
"prompt": "Person dancing to the music",
"image_urls": ["https://example.com/dancer.jpg"],
"audio_url": "https://example.com/music.mp3",
"resolution": "720p",
"duration": 10
}
```
## Mode Description
### Text-to-Video
* `prompt` parameter is required
* Do not pass `image_urls`
* Use `size` to specify aspect ratio
### Image-to-Video
* `image_urls` parameter is required (only 1 image supported)
* `prompt` is optional, used to describe expected actions
* Aspect ratio is determined by the input image, **do not** pass `size`
The system automatically selects the mode based on whether `image_urls` is included
**Query Task Results**
Video generation is an asynchronous task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Wan2.6 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/wan2.6/generation
POST https://api.apimart.ai/v1/videos/generations
- Alibaba Cloud Wanxiang video generation model
- Supports Text-to-Video and Image-to-Video
- Supports 720p/1080p resolution, 5/10/15 seconds duration
- Supports automatic prompt extension and audio generation
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.6",
"prompt": "A cute cat running on the grass",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 5
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan2.6",
"prompt": "A cute cat running on the grass",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 5
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan2.6",
prompt: "A cute cat running on the grass",
aspect_ratio: "16:9",
resolution: "720p",
duration: 5
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan2.6",
"prompt": "A cute cat running on the grass",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "wan2.6",
"prompt": "A cute cat running on the grass",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 5
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"wan2.6",
"prompt" => "A cute cat running on the grass",
"aspect_ratio" => "16:9",
"resolution" => "720p",
"duration" => 5
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "wan2.6",
prompt: "A cute cat running on the grass",
aspect_ratio: "16:9",
resolution: "720p",
duration: 5
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "wan2.6",
"prompt": "A cute cat running on the grass",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 5
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""wan2.6"",
""prompt"": ""A cute cat running on the grass"",
""aspect_ratio"": ""16:9"",
""resolution"": ""720p"",
""duration"": 5
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name, fixed as `wan2.6`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description
Required for text-to-video mode. Describe scenes, actions, and styles in detail for better results
Example: `"A cute cat stretching in the sunlight"`
Reference image URL array (only 1 image supported)
Required for image-to-video mode. Supports publicly accessible image URLs
Example: `["https://example.com/image.jpg"]`
The system automatically selects text-to-video or image-to-video mode based on whether `image_urls` is included
Negative prompt describing unwanted content
Example: `"blurry, low quality, distorted"`
Video aspect ratio
Options:
* `16:9` - Landscape (default)
* `9:16` - Portrait
* `1:1` - Square
* `4:3` - Landscape
* `3:4` - Portrait
Default: `16:9`
Not supported in image-to-video mode
Video resolution
Options:
* `720p` - Standard (default)
* `1080p` - High definition
Default: `720p`
480p resolution is not supported
Billed per second. Pricing varies by resolution. Please refer to the model marketplace for specific pricing
Video duration (seconds)
Supported values: `5`, `10`, `15` seconds only
Default: `5`
Random seed for reproducible results
Example: `12345`
Whether to automatically extend the prompt
When enabled, the system will automatically optimize and enrich your prompt
Whether to automatically add audio
When enabled, the system will generate matching audio for the video
Specified audio URL
Takes priority over the `audio` parameter
Audio duration cannot exceed video duration. If audio is shorter than video duration, the first part of the video will have sound while the rest will be silent.
Shot type
Options:
* `single` - Single shot
* `multi` - Multiple shots
Whether to add watermark
Effect template name for image-to-video special effects mode
When using effects mode:
* Only one image is required (passed via `image_urls`)
* No prompt is needed (model ignores the `prompt` field)
**General Effects:**
* `squish` - Squish & Squeeze
* `rotation` - Rotation
* `poke` - Poke
* `inflate` - Balloon Inflate
* `dissolve` - Molecular Dissolve
* `melt` - Heat Wave Melt
* `icecream` - Ice Cream Planet
* `flying` - Magic Levitation
**Single Person Effects:**
* `carousel` - Time Carousel
* `singleheart` - Love You
* `dance1` - Swing Moment
* `dance2` - Dance Move
For more effects, refer to [Alibaba Wanxiang Template Documentation](https://help.aliyun.com/zh/model-studio/wanx-video-effects)
## Resolution and Aspect Ratio Combinations
| Aspect Ratio | Description | 720p Size | 1080p Size |
| ------------ | ------------------- | --------- | ---------- |
| `16:9` | Landscape (default) | 1280×720 | 1920×1080 |
| `9:16` | Portrait | 720×1280 | 1080×1920 |
| `1:1` | Square | 960×960 | 1440×1440 |
| `4:3` | Landscape | 1088×832 | 1632×1248 |
| `3:4` | Portrait | 832×1088 | 1248×1632 |
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video (Simple Request)
```json theme={null}
{
"model": "wan2.6",
"prompt": "A cute cat stretching in the sunlight"
}
```
### Case 2: Text-to-Video (Full Parameters)
```json theme={null}
{
"model": "wan2.6",
"prompt": "A cute cat running on the grass",
"negative_prompt": "blurry, low quality, distorted",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 5,
"seed": 12345,
"prompt_extend": true,
"audio": true,
"shot_type": "single",
"watermark": false
}
```
### Case 3: Image-to-Video
```json theme={null}
{
"model": "wan2.6",
"prompt": "A kitten running on the ground",
"image_urls": ["https://upload.apimart.ai/f/apimart-models-images/9998233432754770-c059992d-9b01-47d5-810d-ea0502ac9279-image_task_01KD7SSXDBCEWZ869D6PF249ZW_0.png"],
"resolution": "1080p",
"duration": 10
}
```
### Case 4: Image-to-Video (Base64 Image)
```json theme={null}
{
"model": "wan2.6",
"prompt": "Make the cat stand up and walk",
"image_urls": ["data:image/png;base64,iVBORw0KGgo..."],
"duration": 5
}
```
## Mode Description
### Text-to-Video
* `prompt` parameter is required
* `image_urls` parameter is not needed
### Image-to-Video
* `image_urls` parameter is required (only 1 image supported)
* `prompt` parameter is optional, used to describe expected actions
The system automatically selects the mode based on whether `image_urls` is included in the request
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# wan2.6-i2v-flash Image-to-Video
Source: https://docs.apimart.ai/en/api-reference/videos/wan2.6/i2v-flash-generation
POST https://api.apimart.ai/v1/videos/generations
- Wanxiang 2.6 fast image-to-video model
- Generates smooth video from first-frame image and text prompts
- Supports audio/silent toggle, multi-shot narration, custom audio
- Supports 720p/1080p resolution, 2-15 seconds duration
- Supports video effect templates
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.6-i2v-flash",
"prompt": "The person turns around and smiles",
"image_urls": ["https://example.com/portrait.jpg"],
"resolution": "1080p",
"duration": 5
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan2.6-i2v-flash",
"prompt": "The person turns around and smiles",
"image_urls": ["https://example.com/portrait.jpg"],
"resolution": "1080p",
"duration": 5
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan2.6-i2v-flash",
prompt: "The person turns around and smiles",
image_urls: ["https://example.com/portrait.jpg"],
resolution: "1080p",
duration: 5
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan2.6-i2v-flash",
"prompt": "The person turns around and smiles",
"image_urls": []string{"https://example.com/portrait.jpg"},
"resolution": "1080p",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "wan2.6-i2v-flash",
"prompt": "The person turns around and smiles",
"image_urls": ["https://example.com/portrait.jpg"],
"resolution": "1080p",
"duration": 5
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"wan2.6-i2v-flash",
"prompt" => "The person turns around and smiles",
"image_urls" => ["https://example.com/portrait.jpg"],
"resolution" => "1080p",
"duration" => 5
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "wan2.6-i2v-flash",
prompt: "The person turns around and smiles",
image_urls: ["https://example.com/portrait.jpg"],
resolution: "1080p",
duration: 5
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "wan2.6-i2v-flash",
"prompt": "The person turns around and smiles",
"image_urls": ["https://example.com/portrait.jpg"],
"resolution": "1080p",
"duration": 5
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""wan2.6-i2v-flash"",
""prompt"": ""The person turns around and smiles"",
""image_urls"": [""https://example.com/portrait.jpg""],
""resolution"": ""1080p"",
""duration"": 5
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance, please top up",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name, fixed as `wan2.6-i2v-flash`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Reference image URL array (only 1 first-frame image supported)
Supports publicly accessible image URLs or Base64 encoding (`data:image/png;base64,...`)
Example: `["https://example.com/image.jpg"]`
Image requirements:
* Format: JPEG, JPG, PNG (no transparency), BMP, WEBP
* Resolution: width/height range 240-8000 pixels
* Size: ≤ 10MB
Video content description
Optional but recommended for image-to-video, describes expected actions and effects
Clearly specify subject, action, camera and style for better results
Example: `"The person in the image smiles and waves, camera slowly zooms in"`
Negative prompt, describes unwanted content
Maximum 500 characters
Example: `"blurry, low quality, distorted"`
Video resolution
Options:
* `720p` - HD
* `1080p` - FHD (default)
Default: `1080p`
Resolution directly affects pricing, 1080p is more expensive than 720p. Aspect ratio is determined by the input image.
Video duration (seconds)
Supported range: `2` to `15` seconds (integer)
Default: `5`
Whether to generate audio
Set to `true`: automatically generates matching background music/sound effects (default)
Set to `false`: outputs silent video
Default: `true`
Not supported when the model is `wan2.6-i2v`.
Custom audio URL (wav/mp3, 3-30 seconds, ≤ 15MB)
Lower priority than `audio`: ignored when `audio=false`
If audio is longer than video duration, it will be trimmed; if shorter, the remaining part will be silent
Audio file requirements:
* Format: wav, mp3
* Duration: 3-30 seconds
* Size: ≤ 15MB
Whether to enable smart prompt rewriting
Significantly improves results for shorter prompts, but increases processing time
Default: `true`
Shot type, requires `prompt_extend=true`
Options:
* `single` - Single shot (default), outputs a continuous single-shot video
* `multi` - Multi-shot, outputs a narrative video with multiple shot transitions
`shot_type` has higher priority than `prompt`. Even if the prompt mentions "multi-shot", setting `single` will still output a single shot.
Random seed (≥0), specifying the same seed can reproduce similar results
Example: `12345`
Whether to add an "AI Generated" watermark (bottom right)
Default: `false`
## Audio Control
| Parameter Combination | Result |
| ----------------------------------- | ------------------------------------------ |
| No `audio` or `audio_url` | Auto-generated audio (default) |
| `audio_url: "https://..."` | Use specified audio |
| `audio: false` | Silent video |
| `audio: false` + `audio_url: "..."` | Silent video (`audio` has higher priority) |
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` on initial submission
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Minimal Request
```json theme={null}
{
"model": "wan2.6-i2v-flash",
"image_urls": ["https://example.com/image.jpg"]
}
```
### Case 2: Full Parameters
```json theme={null}
{
"model": "wan2.6-i2v-flash",
"prompt": "The person in the image smiles and waves, camera slowly zooms in",
"image_urls": ["https://example.com/image.jpg"],
"negative_prompt": "blurry, low quality, distorted",
"resolution": "1080p",
"duration": 10,
"seed": 12345,
"prompt_extend": true,
"shot_type": "multi",
"audio": true,
"watermark": false
}
```
### Case 3: Custom Audio
```json theme={null}
{
"model": "wan2.6-i2v-flash",
"prompt": "Person dancing to the music",
"image_urls": ["https://example.com/dancer.jpg"],
"audio_url": "https://example.com/music.mp3",
"resolution": "1080p",
"duration": 10
}
```
### Case 4: Silent Video
```json theme={null}
{
"model": "wan2.6-i2v-flash",
"prompt": "Flower slowly blooming",
"image_urls": ["https://example.com/flower.jpg"],
"audio": false,
"resolution": "720p",
"duration": 5
}
```
### Case 5: Effect Template
```json theme={null}
{
"model": "wan2.6-i2v-flash",
"image_urls": ["https://example.com/person.jpg"],
"template": "flying",
"resolution": "720p"
}
```
### Case 6: Base64 Image
```json theme={null}
{
"model": "wan2.6-i2v-flash",
"prompt": "Make the cat stand up and walk",
"image_urls": ["data:image/png;base64,iVBORw0KGgo..."],
"duration": 5
}
```
**Query Task Results**
Video generation is an asynchronous task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Wan2.7-R2V Reference-to-Video
Source: https://docs.apimart.ai/en/api-reference/videos/wan2.7-r2v/generation
POST https://api.apimart.ai/v1/videos/generations
- Alibaba Cloud Wanxiang 2.7 reference-to-video model
- Generate a new video with consistent style, characters, and scenes based on one or more reference images/videos
- Supports character consistency, style transfer, and multi-asset combination
- Supports reference voice (reference_voice) to control character voice
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.7-r2v",
"prompt": "This person walks down the street surrounded by heavy traffic",
"image_with_roles": [{"url": "https://cdn.example.com/character.jpg", "role": "reference_image"}],
"resolution": "1080P",
"duration": 8
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan2.7-r2v",
"prompt": "This person walks down the street surrounded by heavy traffic",
"image_with_roles": [{"url": "https://cdn.example.com/character.jpg", "role": "reference_image"}],
"resolution": "1080P",
"duration": 8
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan2.7-r2v",
prompt: "This person walks down the street surrounded by heavy traffic",
image_with_roles: [{ url: "https://cdn.example.com/character.jpg", role: "reference_image" }],
resolution: "1080P",
duration: 8
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan2.7-r2v",
"prompt": "This person walks down the street surrounded by heavy traffic",
"image_with_roles": []map[string]string{
{"url": "https://cdn.example.com/character.jpg", "role": "reference_image"},
},
"resolution": "1080P",
"duration": 8,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "wan2.7-r2v",
"prompt": "This person walks down the street surrounded by heavy traffic",
"image_with_roles": [{"url": "https://cdn.example.com/character.jpg", "role": "reference_image"}],
"resolution": "1080P",
"duration": 8
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"wan2.7-r2v",
"prompt" => "This person walks down the street surrounded by heavy traffic",
"image_with_roles" => [["url" => "https://cdn.example.com/character.jpg", "role" => "reference_image"]],
"resolution" => "1080P",
"duration" => 8
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "wan2.7-r2v",
prompt: "This person walks down the street surrounded by heavy traffic",
image_with_roles: [{ url: "https://cdn.example.com/character.jpg", role: "reference_image" }],
resolution: "1080P",
duration: 8
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "wan2.7-r2v",
"prompt": "This person walks down the street surrounded by heavy traffic",
"image_with_roles": [["url": "https://cdn.example.com/character.jpg", "role": "reference_image"]],
"resolution": "1080P",
"duration": 8
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""wan2.7-r2v"",
""prompt"": ""This person walks down the street surrounded by heavy traffic"",
""image_with_roles"": [{""url"": ""https://cdn.example.com/character.jpg"", ""role"": ""reference_image""}],
""resolution"": ""1080P"",
""duration"": 8
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name, fixed as `wan2.7-r2v`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description, up to 5000 characters
For multiple images/videos, use "image 1", "image 2", "video 1", etc. to reference the corresponding reference assets (in order of input)
Example: `"The character in image 1 enters the scene in image 2 and looks around"`
Image array with roles; at least one of this and `video_urls` must be provided
Fields for each object:
* `url` (string): image URL
* `role` (string): image role
* `reference_image` - reference image (default)
* `first_frame` - specified first frame (when provided, `size` is ignored and the aspect ratio follows the first-frame image)
* `reference_voice` (string, optional): voice sample audio URL for that reference character, used to control the character's voice in the generated video
Example:
```json theme={null}
[
{
"url": "https://cdn.example.com/character.jpg",
"role": "reference_image",
"reference_voice": "https://cdn.example.com/voice_sample.mp3"
},
{ "url": "https://cdn.example.com/start.jpg", "role": "first_frame" }
]
```
Reference video URL array, up to 5 videos (total images + videos ≤ 5)
At least one of this and `image_with_roles` must be provided
**Video constraints:**
* Format: mp4, mov
* Duration: 1–30s
* Resolution: width and height in the range \[240, 4096] pixels
* Aspect ratio: 1:8 – 8:1
* File size: up to 100MB
Negative prompt describing unwanted content, up to 500 characters
Video resolution
Options:
* `720P` - Standard
* `1080P` - High definition (default)
Video duration (seconds)
Supported range: `2` \~ `15` seconds
Default: `5`
When the reference assets include a video: an integer between \[2, 10].
When the reference assets do not include a video: an integer between \[2, 15].
Aspect ratio
Supported formats:
* `16:9` - Landscape widescreen (default)
* `9:16` - Portrait
* `1:1` - Square
* `4:3` - Landscape
* `3:4` - Portrait
When `first_frame` is provided via `image_with_roles`, this parameter is ignored and the aspect ratio follows the first-frame image
Whether to enable intelligent prompt rewriting
Significantly improves results for short prompts, but increases processing time
Default: `true`
Whether to add "AI Generated" watermark to the generated video
* `true`: add watermark
* `false`: no watermark (default)
Seed integer used to control the randomness of generated content
Value range: integer `≥0`
* For identical requests, the model generates different results when receiving different seed values (e.g., omitting seed)
* For identical requests, the model generates similar results when receiving the same seed value, but exact consistency is not guaranteed
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier
## Use Cases
### Case 1: Single Reference Image (Simplest)
```json theme={null}
{
"model": "wan2.7-r2v",
"prompt": "This person walks down the street surrounded by heavy traffic",
"image_with_roles": [
{ "url": "https://cdn.example.com/character.jpg", "role": "reference_image" }
]
}
```
### Case 2: Multiple Reference Images
```json theme={null}
{
"model": "wan2.7-r2v",
"prompt": "The character in image 1 enters the scene in image 2 and mimics the pose in image 3",
"image_with_roles": [
{ "url": "https://cdn.example.com/person.jpg", "role": "reference_image" },
{ "url": "https://cdn.example.com/background.jpg", "role": "reference_image" },
{ "url": "https://cdn.example.com/pose.jpg", "role": "reference_image" }
],
"resolution": "1080P",
"duration": 8,
"size": "16:9"
}
```
### Case 3: Generation Based on Reference Video
```json theme={null}
{
"model": "wan2.7-r2v",
"prompt": "Generate a beach sunset scene in the style of the reference video",
"video_urls": ["https://cdn.example.com/style_reference.mp4"],
"resolution": "720P",
"duration": 8
}
```
### Case 4: Specified First Frame + Reference Image
```json theme={null}
{
"model": "wan2.7-r2v",
"prompt": "The reference character starts from this position and walks forward",
"image_with_roles": [
{ "url": "https://cdn.example.com/character.jpg", "role": "reference_image" },
{ "url": "https://cdn.example.com/start.jpg", "role": "first_frame" }
],
"resolution": "1080P",
"duration": 8
}
```
### Case 5: Reference Image + Reference Voice (Precise)
```json theme={null}
{
"model": "wan2.7-r2v",
"prompt": "This person walks down the street while speaking",
"image_with_roles": [
{
"url": "https://cdn.example.com/character.jpg",
"role": "reference_image",
"reference_voice": "https://cdn.example.com/voice_sample.mp3"
}
],
"resolution": "1080P",
"duration": 10
}
```
## Image Reference Rules
With multiple reference images, use numeric indices in the `prompt` to refer to them:
* 1st image → "image 1" or "the first image"
* 1st video → "video 1" or "the first video"
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Wan2.7-VideoEdit Video Editing
Source: https://docs.apimart.ai/en/api-reference/videos/wan2.7-videoedit/generation
POST https://api.apimart.ai/v1/videos/generations
- Alibaba Cloud Wanxiang 2.7 video editing model
- AI editing based on existing videos: style transfer, content replacement, element addition
- Optionally accepts reference images to specify target style or appearance
- Supports keeping the original video duration or customizing the output duration
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.7-videoedit",
"video_urls": ["https://cdn.example.com/original.mp4"],
"prompt": "Replace the background with a snowy mountain scene",
"resolution": "1080P"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan2.7-videoedit",
"video_urls": ["https://cdn.example.com/original.mp4"],
"prompt": "Replace the background with a snowy mountain scene",
"resolution": "1080P"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan2.7-videoedit",
video_urls: ["https://cdn.example.com/original.mp4"],
prompt: "Replace the background with a snowy mountain scene",
resolution: "1080P"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan2.7-videoedit",
"video_urls": []string{"https://cdn.example.com/original.mp4"},
"prompt": "Replace the background with a snowy mountain scene",
"resolution": "1080P",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "wan2.7-videoedit",
"video_urls": ["https://cdn.example.com/original.mp4"],
"prompt": "Replace the background with a snowy mountain scene",
"resolution": "1080P"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"wan2.7-videoedit",
"video_urls" => ["https://cdn.example.com/original.mp4"],
"prompt" => "Replace the background with a snowy mountain scene",
"resolution" => "1080P"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "wan2.7-videoedit",
video_urls: ["https://cdn.example.com/original.mp4"],
prompt: "Replace the background with a snowy mountain scene",
resolution: "1080P"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "wan2.7-videoedit",
"video_urls": ["https://cdn.example.com/original.mp4"],
"prompt": "Replace the background with a snowy mountain scene",
"resolution": "1080P"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""wan2.7-videoedit"",
""video_urls"": [""https://cdn.example.com/original.mp4""],
""prompt"": ""Replace the background with a snowy mountain scene"",
""resolution"": ""1080P""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Video generation model name, fixed as `wan2.7-videoedit`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Source video URL array for editing
**Only the 1st video is used**
**Video constraints:**
* Format: mp4, mov
* Duration: 2–10s
* Resolution: width and height in the range \[240, 4096] pixels
* Aspect ratio: 1:8 – 8:1
* File size: up to 100MB
Editing instruction describing the desired changes, up to 5000 characters
If omitted, the model performs a default style transfer
Example: `"Change the character's outfit to a red gown"`, `"Replace the background with a snowy mountain scene"`
Negative prompt describing unwanted content, up to 500 characters
Reference image URL array, up to 4 images
Used to specify the target style or appearance (e.g., reference style for style transfer)
Output video resolution
Options:
* `720P` - Standard
* `1080P` - High definition (default)
Output video duration (seconds)
* `0` (default): keep the full original video duration
* Integer between `2-10`: take the specified duration from the start
When `duration=0`, billing is based on the actual duration of the output video
The specified duration cannot exceed the duration of the original `video_urls` video
Output aspect ratio
Supported formats:
* `16:9` - Landscape widescreen
* `9:16` - Portrait
* `1:1` - Square
* `4:3` - Landscape
* `3:4` - Portrait
If omitted, the aspect ratio matches the input video
Whether to enable intelligent prompt rewriting
Significantly improves results for short prompts, but increases processing time
Default: `true`
Whether to add "AI Generated" watermark to the generated video
* `true`: add watermark
* `false`: no watermark (default)
Seed integer used to control the randomness of generated content
Value range: integer `≥0`
* For identical requests, the model generates different results when receiving different seed values (e.g., omitting seed)
* For identical requests, the model generates similar results when receiving the same seed value, but exact consistency is not guaranteed
Additional parameter object
Audio handling mode:
* `auto` (default): AI automatically regenerates matching audio based on the edited video content
* `origin`: force keep the original video audio, suitable for videos with important background sounds/dialogue
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier
## Use Cases
### Case 1: Basic Video Editing (Simplest)
```json theme={null}
{
"model": "wan2.7-videoedit",
"video_urls": ["https://cdn.example.com/original.mp4"],
"prompt": "Replace the background with a snowy mountain scene"
}
```
### Case 2: Style Transfer (With Reference Image)
```json theme={null}
{
"model": "wan2.7-videoedit",
"prompt": "Transfer the video style to the anime style of the reference image",
"video_urls": ["https://cdn.example.com/original.mp4"],
"image_urls": [
"https://cdn.example.com/anime_style.jpg"
],
"resolution": "1080P",
"watermark": false
}
```
### Case 3: Keep Original Video Audio
Suitable for videos with important background sound or dialogue:
```json theme={null}
{
"model": "wan2.7-videoedit",
"video_urls": ["https://cdn.example.com/speech.mp4"],
"prompt": "Replace the background with a mountain path",
"metadata": { "audio_setting": "origin" }
}
```
### Case 4: Full Parameters
```json theme={null}
{
"model": "wan2.7-videoedit",
"prompt": "Change the character's outfit to a red gown",
"negative_prompt": "blurry, distorted",
"video_urls": ["https://cdn.example.com/original.mp4"],
"image_urls": ["https://cdn.example.com/reference.jpg"],
"resolution": "1080P",
"duration": 0,
"size": "16:9",
"prompt_extend": true,
"watermark": false,
"seed": 888,
"metadata": {
"audio_setting": "origin"
}
}
```
## Audio Handling
| audio\_setting | Description | Suitable Scenarios |
| ---------------- | --------------------------------------------------------------- | --------------------------------------------------------------------- |
| `auto` (default) | AI regenerates matching audio based on the edited video content | Major visual style changes where you want audio to update accordingly |
| `origin` | Force keep the original video audio track | Videos with important background music or dialogue |
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Wan2.7 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/wan2.7/generation
POST https://api.apimart.ai/v1/videos/generations
- Alibaba Cloud Wanxiang 2.7 video generation model (unified entry)
- Automatically routed based on parameters: Text-to-Video / Image-to-Video (first frame, first-last frame, video continuation)
- Supports 720P/1080P resolution, 2-15 seconds duration
- Supports custom audio (background music in text-to-video mode, driving audio in image-to-video mode)
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.7",
"prompt": "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
"resolution": "1080P",
"duration": 8,
"size": "16:9"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan2.7",
"prompt": "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
"resolution": "1080P",
"duration": 8,
"size": "16:9"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan2.7",
prompt: "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
resolution: "1080P",
duration: 8,
size: "16:9"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan2.7",
"prompt": "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
"resolution": "1080P",
"duration": 8,
"size": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "wan2.7",
"prompt": "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
"resolution": "1080P",
"duration": 8,
"size": "16:9"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"wan2.7",
"prompt" => "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
"resolution" => "1080P",
"duration" => 8,
"size" => "16:9"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "wan2.7",
prompt: "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
resolution: "1080P",
duration: 8,
size: "16:9"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "wan2.7",
"prompt": "A coastal road at sunset, slow-motion camera push-in, cinematic feel",
"resolution": "1080P",
"duration": 8,
"size": "16:9"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""wan2.7"",
""prompt"": ""A coastal road at sunset, slow-motion camera push-in, cinematic feel"",
""resolution"": ""1080P"",
""duration"": 8,
""size"": ""16:9""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Mode Routing
`wan2.7` is a unified entry for text-to-video and image-to-video. The backend automatically determines the mode based on the incoming parameters. **Both modes are billed identically**:
| Condition | Routes To | Mode Description |
| ------------------------------------------------------------------- | -------------- | --------------------------------------------------- |
| Any of `image_urls` / `image_with_roles` / `video_urls` is provided | Image-to-Video | First-frame / First-last frame / Video continuation |
| None of the above parameters provided | Text-to-Video | Generate video purely from text description |
## Request Parameters
Video generation model name, fixed as `wan2.7`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Video content description, up to 5000 characters
* **Text-to-Video mode** (when no image/video provided): required
* **Image-to-Video mode**: optional, but recommended to guide camera movement and actions
Example: `"A cat chasing butterflies on the grass, bright sunshine, slow motion"`
Image URL array. Providing it automatically enters Image-to-Video mode
* **1 image**: first-frame to video
* **2 images**: first-last frame to video (1st = first frame, 2nd = last frame)
Use either this or `image_with_roles`
`image_urls` conflicts with `audio_url`; they cannot be provided at the same time
Image array with roles, alternative to `image_urls`, used to precisely specify the role of each image
Fields for each object:
* `url` (string): image URL (supports http/https)
* `role` (string): image role, `first_frame` / `last_frame`, default `first_frame`
Example:
```json theme={null}
[
{ "url": "https://cdn.example.com/start.jpg", "role": "first_frame" },
{ "url": "https://cdn.example.com/end.jpg", "role": "last_frame" }
]
```
`image_with_roles` conflicts with `audio_url`; they cannot be provided at the same time
Video URL array. Providing it enters **video continuation** mode (only the 1st video is used)
`video_urls` conflicts with `audio_url`; they cannot be provided at the same time
**Video constraints:**
* Format: mp4, mov
* Duration: 2–10s
* Resolution: width and height in the range \[240, 4096] pixels
* Aspect ratio: 1:8 – 8:1
* File size: up to 100MB
Negative prompt describing unwanted content, up to 500 characters
Example: `"blurry, distorted, low quality"`
Video resolution
Options:
* `720P` - Standard
* `1080P` - High definition (default)
Video duration (seconds)
Supported range: `2` \~ `15` seconds
Default: `5`
Aspect ratio, **only effective in Text-to-Video mode** (when no image/video provided)
Supported formats:
* `16:9` - Landscape widescreen (default)
* `9:16` - Portrait
* `1:1` - Square
* `4:3` - Landscape
* `3:4` - Portrait
This parameter is ignored in Image-to-Video mode; the aspect ratio is determined automatically by the input image
Custom audio URL
* **Text-to-Video mode**: used as background music
* **Image-to-Video mode**: used as driving audio, synchronized with on-screen actions
Format: wav / mp3, duration 2-30 seconds, file size ≤ 15MB
`audio_url` conflicts with `video_urls`, `image_urls`, and `image_with_roles`; they cannot be provided at the same time
Whether to enable intelligent prompt rewriting
Significantly improves results for short prompts, but increases processing time
Default: `true`
Whether to add "AI Generated" watermark to the generated video
* `true`: add watermark
* `false`: no watermark (default)
Seed integer used to control the randomness of generated content
Value range: integer `≥0`
* For identical requests, the model generates different results when receiving different seed values (e.g., omitting seed)
* For identical requests, the model generates similar results when receiving the same seed value, but exact consistency is not guaranteed
## Response
Response status code, 200 on success
Response data array
Task status, `submitted` when initially submitted
Unique task identifier for querying task status and results
## Use Cases
### Case 1: Text-to-Video (Simplest Request)
```json theme={null}
{
"model": "wan2.7",
"prompt": "A coastal road at sunset, slow-motion camera push-in, cinematic feel"
}
```
### Case 2: Text-to-Video (Full Parameters)
```json theme={null}
{
"model": "wan2.7",
"prompt": "A cat chasing butterflies on the grass, bright sunshine, slow motion",
"negative_prompt": "blurry, distorted, low quality",
"resolution": "1080P",
"duration": 8,
"size": "16:9",
"audio_url": "https://cdn.example.com/bgm.mp3",
"prompt_extend": true,
"watermark": false,
"seed": 42
}
```
### Case 3: First-Frame to Video
```json theme={null}
{
"model": "wan2.7",
"prompt": "The character slowly stands up and walks toward the camera",
"image_urls": ["https://cdn.example.com/person.jpg"],
"resolution": "1080P",
"duration": 8
}
```
### Case 4: First-Last Frame to Video
```json theme={null}
{
"model": "wan2.7",
"prompt": "The camera pans slowly from the beach to the mountaintop",
"image_urls": [
"https://cdn.example.com/beach.jpg",
"https://cdn.example.com/mountain.jpg"
],
"resolution": "1080P",
"duration": 10
}
```
> With 2 images: the 1st is the first frame, the 2nd is the last frame. You can also use `image_with_roles` for precise specification.
### Case 5: Video Continuation
```json theme={null}
{
"model": "wan2.7",
"prompt": "Continue walking forward, camera follows",
"video_urls": ["https://cdn.example.com/clip.mp4"],
"resolution": "1080P",
"duration": 8
}
```
### Case 6: Image + Driving Audio
```json theme={null}
{
"model": "wan2.7",
"prompt": "The character moves to the rhythm of the music",
"image_urls": ["https://cdn.example.com/dancer.jpg"],
"audio_url": "https://cdn.example.com/beat.mp3",
"resolution": "1080P",
"duration": 8
}
```
## Mode Selection Guide
| Requirement | Recommended Approach |
| ----------------------------- | -------------------------------------------- |
| Generate video from text only | Pass only `prompt` (no image/video) |
| Make an image "come alive" | Pass 1 image to `image_urls` |
| Control start and end frames | Pass 2 images to `image_urls` (first + last) |
| Extend an existing video | Pass video to `video_urls` |
| Make image move to music | Pass image + `audio_url` |
**Query Task Results**
Video generation is an async task that returns a `task_id` upon submission. Use the [Get Task Status](/en/api-reference/tasks/status) endpoint to query generation progress and results.
# Wan3.0 Video Generation
Source: https://docs.apimart.ai/en/api-reference/videos/wan3.0-video/generation
POST https://api.apimart.ai/v1/videos/generations
- Alibaba Cloud Wanxiang 3.0 all-in-one reference video model
- Text-to-video / first frame / first+last frame / multi-modal reference / file or link reference
- Resolution 480P / 720P / 1080P, duration 2–30 seconds, or `-1` for model-chosen length
- Supports images, video, audio, documents, and public web pages as references
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
"resolution": "720P",
"size": "16:9",
"duration": 5
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan3.0-video",
prompt: "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
resolution: "720P",
size: "16:9",
duration: 5,
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
## Authorization
All endpoints require Bearer Token authentication
Get your API Key from the [API Key Management Page](https://apimart.ai/keys):
```
Authorization: Bearer YOUR_API_KEY
```
## Generation Modes
Model name is fixed to **`wan3.0-video`**. Modes are selected by request fields:
| Mode | Typical inputs |
| --------------------- | ---------------------------------------------------------------------------------- |
| Text-to-video | `prompt` only |
| First-frame video | one item in `image_urls` (frame family) |
| First + last frame | two items in `image_urls`, or `image_with_roles` with `first_frame` / `last_frame` |
| Reference video | reference images / videos / audio; prompt may use “图1 / 视频1 / 音频1” style labels |
| File / page reference | `file_url` or `link_url` (`prompt` optional) |
## Request Parameters
### Basics
Fixed value: `wan3.0-video`
Whether to run content moderation before submitting the video task.
* `true`: use `omni-moderation-latest` to review prompts and input images
* `false` or omitted: do not send a moderation request, adding no moderation cost or latency (default)
Text description. **Required unless** media fields are provided (at least one of prompt or media).
* Max **20,000** characters; overflow is truncated automatically (no error)
* In reference mode, use “图N / 视频N / 音频N” to address assets; indices follow order **within each media type**
Output resolution (case-insensitive)
* `480P`
* `720P`
* `1080P` (**default**, highest price)
Omitting `resolution` bills at **1080P**. Pass `480P` or `720P` explicitly when cost matters.
Aspect ratio. `aspect_ratio` is also accepted.
* `adaptive` (default)
* `16:9` / `4:3` / `1:1` / `3:4` / `9:16`
Duration in seconds:
* `2`–`30`: fixed output length (default `5`)
* `-1`: **model decides** the duration
With reference video input, total input video duration + output duration must be ≤ 30 seconds. When `duration` is `-1`, the model chooses the length, which must still satisfy this constraint.
Whether the output includes an audio track. Default `true`. **Price is the same with or without audio.**
Random seed in `[0, 2147483647]`
Whether to add a watermark. Default `false`
How bare `image_urls` are classified:
* `frame` — first/last frame family
* `reference` — reference family
If omitted, classification is automatic (see mutual exclusion rules).
### Media inputs
Image URL array. Role assignment follows mutual exclusion rules.
Public URL or Base64 (`data:image/png;base64,...`).
Images with explicit roles. Each item:
* `url`: image address
* `role`: `first_frame` / `last_frame` / `reference_image` (common aliases accepted)
Reference videos, up to **5** clips; each 1–15s, **total ≤ 15s**
Reference audio, up to **5** clips; each 1–15s, **total ≤ 15s**
Single reference audio (single-value form of `audio_urls`)
Reference document URL, at most **1**. **Cannot be combined with `link_url`.**
Formats include docx / doc / xlsx / xls / pptx / ppt / pdf / txt / key / pages / numbers / md, ≤100MB, ≤50 pages.
Public web page URL, at most **1**. Login-free pages only. **Cannot be combined with `file_url`.**
## Mutual Exclusion of Media Families
Media belongs to one of two families and **must not be mixed** (validated before submit → 400, no task, no charge):
| Family | Members | Meaning |
| -------------------- | ----------------------------------------------------------------------- | -------------------------------------- |
| **Frame family** | `first_frame`, `last_frame` | Strict first / last frame of the video |
| **Reference family** | `reference_image`, `reference_video`, `reference_audio`, `file`, `link` | Model interprets content freely |
### How bare `image_urls` are assigned
1. If `generation_type` is set → use it (`frame` / `reference`)
2. Else if the request already has reference-family inputs (`video_urls` / `audio_urls` / `audio_url` / `file_url` / `link_url`) → treat as `reference_image`
3. Else → frame family: first item `first_frame`, second `last_frame` (same as `wan2.7`)
Use `image_with_roles` when you need explicit control.
### Media limits and formats
| Type | Limits |
| ------------------ | --------------------------------------------------------------------------------- |
| First / last frame | ≤ 1 each |
| Reference images | ≤ 10 |
| Reference video | ≤ 5 clips, 1–15s each, total ≤15s; mp4/mov; edge 240–4096 px, aspect ≤8:1, ≤100MB |
| Reference audio | ≤ 5 clips, 1–15s each, total ≤15s; wav/mp3; ≤15MB |
| Images | JPEG/JPG/PNG (no alpha) / BMP / WEBP; edge 240–8000 px, aspect ≤8:1, ≤20MB |
| Documents | ≤100MB, ≤50 pages |
| Web pages | Public, login-free URLs |
## Request Examples
### Text-to-video
```json theme={null}
{
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
"resolution": "720P",
"size": "16:9",
"duration": 5
}
```
### First-frame video
```json theme={null}
{
"model": "wan3.0-video",
"prompt": "The person in the frame starts freestyle rapping, camera slowly pushes in",
"image_urls": ["https://example.com/first.png"],
"resolution": "720P",
"duration": 5
}
```
### First + last frame
```json theme={null}
{
"model": "wan3.0-video",
"prompt": "Smile gradually becomes laughter, background light shifts from cool to warm",
"image_urls": [
"https://example.com/first.png",
"https://example.com/last.jpg"
],
"duration": 5
}
```
Or with `image_with_roles`:
```json theme={null}
{
"model": "wan3.0-video",
"prompt": "Smile gradually becomes laughter",
"image_with_roles": [
{"url": "https://example.com/first.png", "role": "first_frame"},
{"url": "https://example.com/last.jpg", "role": "last_frame"}
],
"duration": 5
}
```
### Multi-modal reference
```json theme={null}
{
"model": "wan3.0-video",
"prompt": "视频1抱着图1,在图3的椅子上弹奏一支舒缓的乡村民谣,并说道:\"今天的阳光真好。\"",
"generation_type": "reference",
"image_urls": [
"https://example.com/object1.jpg",
"https://example.com/object2.png",
"https://example.com/chair.png"
],
"video_urls": ["https://example.com/role.mp4"],
"resolution": "480P",
"duration": 5
}
```
> With `video_urls` present, bare `image_urls` auto-classify as reference images; setting `generation_type: "reference"` is clearer.
### File reference video
`prompt` may be omitted; generation is driven by the document:
```json theme={null}
{
"model": "wan3.0-video",
"file_url": "https://example.com/glass.pptx",
"resolution": "480P",
"duration": 10
}
```
### Web page reference video
```json theme={null}
{
"model": "wan3.0-video",
"prompt": "Turn this article into a short educational video",
"link_url": "https://example.com/article/123",
"duration": 15
}
```
## Billing
**Per second × resolution** (aligned with official list price). Audio on/off does not change price:
| Resolution | Unit price | 5s | 30s |
| ---------- | ------------- | ----- | ------ |
| 480P | **¥0.30** / s | ¥1.50 | ¥9.00 |
| 720P | **¥0.60** / s | ¥3.00 | ¥18.00 |
| 1080P | **¥1.20** / s | ¥6.00 | ¥36.00 |
* Default is **1080P** (most expensive); pass `480P` / `720P` when cost-sensitive
* Billable seconds: for `2`–`30`, use the requested `duration`; for `-1`, use the **actual** output seconds
* `audio: true/false` does **not** affect price
## Limits and Notes
| Item | Notes |
| ---------------- | --------------------------------------------------------------- |
| Duration | Integer `2`–`30`, or `-1` (model decides length) |
| With video input | Input video total duration + output duration ≤ 30s |
| Latency | Typically 1–5 minutes; longer for long clips |
| Result URL | Mirrored to the platform CDN after success for long-term access |
| Prompt | ≤20,000 characters; overflow truncated |
## Common Errors
All are **sync 400** (no task, no charge):
| Case | What to do |
| ----------------------------------- | --------------------------------------------------------------------------- |
| Mixing frame and reference families | Pick one family via `generation_type`, or set roles with `image_with_roles` |
| Both `file_url` and `link_url` | Choose one |
| Invalid `duration` | Only `2`–`30` or `-1` |
| Unsupported resolution (e.g. 4K) | Only `480P` / `720P` / `1080P` |
| More than 10 reference images | Reduce to ≤10 |
| Empty `prompt` and empty media | Provide at least one |
## Response
Status code; 200 on success
Response data array
Task status; `submitted` on create
Task ID for polling
**Query results**
Video generation is async. Poll [Get Task Status](/en/api-reference/tasks/status) or `GET /v1/videos/generations/{task_id}`.
Recommended interval 5–10 seconds; generation typically takes 1–5 minutes. On success, use URLs in `result.videos`.
# APIMart — OpenAI-Compatible API Gateway (GPT-5, Claude, Gemini)
Source: https://docs.apimart.ai/en/index
OpenAI-compatible API for GPT-5, Claude, Gemini. Multi-provider routing, transparent pricing, low latency. Enterprise SLA, SDK support, pay-as-you-go.
One unified OpenAI-compatible endpoint for GPT-5, Claude, and Gemini. Migrate from OpenAI in minutes by simply changing your base URL to `https://api.apimart.ai/v1` — keep your existing SDKs with no code rewrite. Multi-provider routing ensures low latency and high uptime. Transparent pricing, enterprise SLA, and global CDN acceleration.
## Quick Start
OpenAI-compatible Chat API with GPT-5, Claude Sonnet 4.5, Gemini 2.0. Switch base URL, no code changes needed.
## OpenAI-Compatible Endpoints
APIMart provides OpenAI-style endpoints for seamless migration. Simply change your base URL and keep using your existing SDKs. All interfaces follow OpenAI standards with extended support for Claude, Gemini, Sora, and VEO models.
### Chat Completion API
Chat completion with GPT-5, GPT-4o, Claude Sonnet 4.5, Gemini 2.0 Flash. OpenAI-compatible API with streaming support and low latency.
Streaming support and low latency
### Image Creation API
Image creation with GPT-4o Image, Gemini 2.5 Flash Image-preview models. OpenAI-style API for seamless integration.
Text-to-image generation
### Video Creation API
Video creation with OpenAI Sora2, Google VEO3 models. Async task management with status tracking and webhook support.
Async task management with webhooks
## Platform Benefits
### Transparent Pricing
Pay-as-you-go with no subscription required. Clear per-token rates for all models, more affordable than official provider rates while maintaining the same quality and low latency.
* Clear per-token rates for all models
* Volume discounts for enterprise usage
* No hidden fees
* Only pay for what you actually use
### Multi-Provider Routing & Enterprise SLA
Built-in intelligent routing across multiple LLM providers ensures high uptime and low latency. When one provider experiences issues, requests automatically route to backup providers without service interruption.
### Uptime SLA
99.9% uptime with enterprise-grade reliability and automatic failover. Multi-provider routing ensures your requests are always served with minimal latency.
### Global CDN Acceleration
Edge locations worldwide for lowest latency. Optimized routing reduces response time and improves user experience globally.
### Rate Limit Management
Automatic rate limit handling across providers. Intelligent request distribution prevents throttling and ensures smooth operation.
### Real-Time Status
Monitor endpoint health and performance. Track async task progress for image and video creation with webhook notifications. [Check Status →](/en/api-reference/tasks/status)
## SDKs & Code Examples
Official SDKs for Python, Node.js, and Java. All SDKs are OpenAI-compatible, allowing seamless migration by changing only the base URL configuration.
### Python SDK
Install with `pip install openai`. Set base URL and use existing OpenAI code without changes.
```python theme={null}
from openai import OpenAI
client = OpenAI(
base_url="https://api.apimart.ai/v1",
api_key="your-apimart-key"
)
```
### Node.js SDK
Install with `npm install openai`. Configure baseURL parameter to APIMart endpoint and keep your existing integration.
```javascript theme={null}
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://api.apimart.ai/v1',
apiKey: 'your-apimart-key'
});
```
### Java SDK
OpenAI-compatible Java client. Simple configuration change enables access to all APIMart models and providers.
## Migration from OpenAI
Switch to APIMart in under 5 minutes. No code rewrite needed—just change your base URL and API key.
Sign up for APIMart and get your API key from the Console Dashboard.
Change OpenAI base URL to APIMart endpoint. Your existing SDK integration works without modification.
Run your existing code with the new base URL. All OpenAI-compatible endpoints respond with identical format. Check latency and rate limits in Console Dashboard.
## Supported Models via Unified Endpoint
Access leading LLM providers through one OpenAI-compatible gateway. All models available with consistent request/response format.
### Chat Completion Models
Leading language models for chat, completion, and code tasks:
* **GPT-5**: OpenAI flagship model with enhanced reasoning
* **GPT-4o & GPT-4o Mini**: Multimodal models balancing performance and cost
* **Claude Sonnet 4.5 & Haiku 4.5**: Anthropic models for complex reasoning
* **Gemini 2.0 Flash & Flash Thinking**: Google multimodal models
### Image Creation Models
Image creation from text prompts:
* **GPT-4o Image**: OpenAI image creation model
* **Gemini 2.5 Flash Image-preview**: Google efficient image model
### Video Creation Models
Video creation with async task tracking and webhook callbacks:
* **OpenAI Sora2**: OpenAI video creation model
* **Google VEO3**: Google video creation model
### Speech Models
Speech-to-text and text-to-speech via OpenAI-compatible endpoints:
* **Whisper-1**: OpenAI transcription model
* **TTS**: Text-to-speech with multiple voices
## FAQ
Simply change your base URL to `https://api.apimart.ai/v1` and use your APIMart API key. Keep your existing SDKs—no code rewrite needed. Migration typically takes under 5 minutes.
Our enterprise SLA includes 99.9% uptime guarantee, global CDN acceleration, multi-provider routing with automatic failover, and real-time status monitoring. Rate limit management and webhook support are included.
APIMart offers transparent per-token pricing that's more affordable than official provider rates. Pay-as-you-go with no subscription, volume discounts for enterprise usage, and no hidden fees.
Low latency is guaranteed through global CDN acceleration and intelligent multi-provider routing. Edge locations worldwide ensure optimal response times. Real-time status monitoring lets you track performance.
# Query Token Balance
Source: https://docs.apimart.ai/en/api-reference/account/token-balance
GET https://api.apimart.ai/v1/balance
- Query remaining and used credits of the current API Key
- Monitor single token usage
- CORS support for cross-origin requests
- Real-time balance monitoring
Get the remaining and used balance of the current API Key (token). This endpoint is used to monitor the usage of a single token.
```bash cURL theme={null}
curl --request GET \
--url 'https://api.apimart.ai/v1/balance' \
--header 'Authorization: Bearer '
```
```python Python theme={null}
import requests
API_BASE = 'https://api.apimart.ai'
API_KEY = 'sk-xxxxxxxxxxxxxxxxxxxxxx'
headers = {
'Authorization': f'Bearer {API_KEY}'
}
def get_token_balance():
response = requests.get(f'{API_BASE}/v1/balance', headers=headers)
data = response.json()
if data.get('success'):
if data.get('unlimited_quota'):
print("Quota: Unlimited")
else:
print(f"Remaining balance: {data['remain_balance']}")
print(f"Used balance: {data['used_balance']}")
else:
print(f"Query failed: {data.get('message')}")
return data
get_token_balance()
```
```javascript JavaScript theme={null}
const API_BASE = 'https://api.apimart.ai';
const API_KEY = 'sk-xxxxxxxxxxxxxxxxxxxxxx';
async function getTokenBalance() {
const response = await fetch(`${API_BASE}/v1/balance`, {
headers: {
'Authorization': `Bearer ${API_KEY}`
}
});
const data = await response.json();
if (data.success) {
if (data.unlimited_quota) {
console.log('Quota: Unlimited');
} else {
console.log(`Remaining balance: ${data.remain_balance}`);
}
console.log(`Used balance: ${data.used_balance}`);
} else {
console.error('Query failed:', data.message);
}
return data;
}
getTokenBalance();
```
```go Go theme={null}
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type BalanceResponse struct {
Success bool `json:"success"`
Message string `json:"message,omitempty"`
RemainBalance float64 `json:"remain_balance"`
UsedBalance float64 `json:"used_balance"`
UnlimitedQuota bool `json:"unlimited_quota"`
}
func main() {
url := "https://api.apimart.ai/v1/balance"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer ")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result BalanceResponse
json.Unmarshal(body, &result)
if result.Success {
if result.UnlimitedQuota {
fmt.Println("Quota: Unlimited")
} else {
fmt.Printf("Remaining balance: %.2f\n", result.RemainBalance)
}
fmt.Printf("Used balance: %.2f\n", result.UsedBalance)
}
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/balance";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.GET()
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
api_key = 'sk-xxxxxxxxxxxxxxxxxxxxxx'
url = URI("https://api.apimart.ai/v1/balance")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = "Bearer #{api_key}"
response = http.request(request)
data = JSON.parse(response.body)
if data['success']
if data['unlimited_quota']
puts "Quota: Unlimited"
else
puts "Remaining balance: #{data['remain_balance']}"
end
puts "Used balance: #{data['used_balance']}"
else
puts "Query failed: #{data['message']}"
end
```
```swift Swift theme={null}
import Foundation
let apiKey = "sk-xxxxxxxxxxxxxxxxxxxxxx"
let url = URL(string: "https://api.apimart.ai/v1/balance")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var apiKey = "sk-xxxxxxxxxxxxxxxxxxxxxx";
var url = "https://api.apimart.ai/v1/balance";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
var response = await client.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 - Success theme={null}
{
"success": true,
"remain_balance": 10.5,
"remain_credits": 105,
"used_balance": 2.3,
"used_credits": 23,
"unlimited_quota": false
}
```
```json 200 - Unlimited Quota Token theme={null}
{
"success": true,
"remain_balance": -1,
"remain_credits": -1,
"used_balance": 2.3,
"used_credits": 23,
"unlimited_quota": true
}
```
```json 200 - Token Not Found theme={null}
{
"success": false,
"message": "Failed to get token info: record not found"
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Endpoints
```
GET /v1/balance
GET /balance
```
Both endpoints have the same functionality, you can use either one.
## Response
Whether the request was successful
Error message (only returned on failure)
Token remaining balance (returned on success). Returns `-1` when `unlimited_quota` is `true`
Token remaining credits (returned on success). Returns `-1` when `unlimited_quota` is `true`
Token used balance (returned on success)
Token used credits (returned on success)
Whether the token has unlimited quota. `true` means unlimited, `false` means limited
## Use Cases
* Monitor consumption of a single API Key
* Display current token balance in your application
* Set up balance alerts when balance falls below threshold
**Balance Unit Information**
The unit of the balance value depends on system configuration:
* **USD** - US Dollars
* **Credits** - Credits
**Unlimited Quota Token**
When a token is set to unlimited quota:
* `unlimited_quota` field returns `true`
* `remain_balance` field returns `-1`
* `remain_credits` field returns `-1`
* The token has no quota restrictions and can be used without limits
## Common Errors
| Error Message | Cause | Solution |
| ------------------------ | --------------------------------------- | ------------------------------------------- |
| No Authorization header | Authorization header not provided | Add `Authorization: Bearer sk-xxxxx` header |
| Failed to get token info | Token doesn't exist or has been deleted | Check if the token key is correct |
**Security Note**
Your API Key is like a password. Keep it secure and don't share it with others. Always use HTTPS in production.
# Query User Balance
Source: https://docs.apimart.ai/en/api-reference/account/user-balance
GET https://api.apimart.ai/v1/user/balance
- Query overall remaining and used credits of user account
- Get user-level balance information
- CORS support for cross-origin requests
- Real-time balance monitoring
Get the remaining and used balance of the current user account. This endpoint returns user-level balance information, independent of specific tokens, for viewing the overall account balance.
```bash cURL theme={null}
curl --request GET \
--url 'https://api.apimart.ai/v1/user/balance' \
--header 'Authorization: Bearer '
```
```python Python theme={null}
import requests
API_BASE = 'https://api.apimart.ai'
API_KEY = 'sk-xxxxxxxxxxxxxxxxxxxxxx'
headers = {
'Authorization': f'Bearer {API_KEY}'
}
def get_user_balance():
response = requests.get(f'{API_BASE}/v1/user/balance', headers=headers)
data = response.json()
if data.get('success'):
print(f"Remaining balance: {data['remain_balance']}")
print(f"Used balance: {data['used_balance']}")
else:
print(f"Query failed: {data.get('message')}")
return data
get_user_balance()
```
```javascript JavaScript theme={null}
const API_BASE = 'https://api.apimart.ai';
const API_KEY = 'sk-xxxxxxxxxxxxxxxxxxxxxx';
async function getUserBalance() {
const response = await fetch(`${API_BASE}/v1/user/balance`, {
headers: {
'Authorization': `Bearer ${API_KEY}`
}
});
const data = await response.json();
if (data.success) {
console.log(`Remaining balance: ${data.remain_balance}`);
console.log(`Used balance: ${data.used_balance}`);
} else {
console.error('Query failed:', data.message);
}
return data;
}
getUserBalance();
```
```go Go theme={null}
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type BalanceResponse struct {
Success bool `json:"success"`
Message string `json:"message,omitempty"`
RemainBalance float64 `json:"remain_balance"`
UsedBalance float64 `json:"used_balance"`
}
func main() {
url := "https://api.apimart.ai/v1/user/balance"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer ")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result BalanceResponse
json.Unmarshal(body, &result)
if result.Success {
fmt.Printf("Remaining balance: %.2f\n", result.RemainBalance)
fmt.Printf("Used balance: %.2f\n", result.UsedBalance)
}
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/user/balance";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.GET()
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
api_key = 'sk-xxxxxxxxxxxxxxxxxxxxxx'
url = URI("https://api.apimart.ai/v1/user/balance")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = "Bearer #{api_key}"
response = http.request(request)
data = JSON.parse(response.body)
if data['success']
puts "Remaining balance: #{data['remain_balance']}"
puts "Used balance: #{data['used_balance']}"
else
puts "Query failed: #{data['message']}"
end
```
```swift Swift theme={null}
import Foundation
let apiKey = "sk-xxxxxxxxxxxxxxxxxxxxxx"
let url = URL(string: "https://api.apimart.ai/v1/user/balance")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var apiKey = "sk-xxxxxxxxxxxxxxxxxxxxxx";
var url = "https://api.apimart.ai/v1/user/balance";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
var response = await client.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```json 200 - Success theme={null}
{
"success": true,
"remain_balance": 100.0,
"remain_credits": 1000,
"used_balance": 25.5,
"used_credits": 255
}
```
```json 200 - User Quota Query Failed theme={null}
{
"success": false,
"message": "Failed to get user quota: record not found"
}
```
```json 200 - Used Quota Query Failed theme={null}
{
"success": false,
"message": "Failed to get used quota: record not found"
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
## Authorization
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Endpoints
```
GET /v1/user/balance
GET /user/balance
```
Both endpoints have the same functionality, you can use either one.
## Response
Whether the request was successful
Error message (only returned on failure)
User remaining balance (returned on success).
User remaining credits (returned on success).
User used balance (returned on success)
User used credits (returned on success)
## Token Balance vs User Balance
| Comparison | Token Balance (`/v1/balance`) | User Balance (`/v1/user/balance`) |
| ----------- | --------------------------------- | --------------------------------- |
| Scope | Single token | Entire user account |
| Data Source | Token's RemainQuota and UsedQuota | User's quota and used\_quota |
| Use Case | Monitor single API Key usage | View overall account balance |
| Limited By | Token-level quota limits | User-level quota limits |
## Use Cases
* View overall user account balance
* Set up recharge reminders and balance alerts
* Display account balance in user dashboard
**Balance Unit Information**
The unit of the balance value depends on system configuration:
* **USD** - US Dollars
* **CNY** - Chinese Yuan
* **Tokens** - Token count
## Common Errors
| Error Message | Cause | Solution |
| ------------------------ | --------------------------------- | -------------------------------------------------- |
| No Authorization header | Authorization header not provided | Add `Authorization: Bearer sk-xxxxx` header |
| Failed to get user quota | User doesn't exist | Check if the user associated with the token exists |
| Failed to get used quota | Database query error | Contact admin to check system status |
**Security Note**
Your API Key is like a password. Keep it secure and don't share it with others. Always use HTTPS in production.
# Cover Rearrangement
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/cover
POST https://api.apimart.ai/v1/music/generations/coverFlowMusic
Flow Music rearranges an entire song into a new style (cover / restyle), with strength controlling the editing intensity
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/coverFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"clip_id": "abc123-def456",
"instruction": "Rearrange this song in jazz style",
"strength": 0.5
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/coverFlowMusic"
payload = {
"model": "flowmusic",
"clip_id": "abc123-def456",
"instruction": "Rearrange this song in jazz style",
"strength": 0.5
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/coverFlowMusic";
const payload = {
model: "flowmusic",
clip_id: "abc123-def456",
instruction: "Rearrange this song in jazz style",
strength: 0.5
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVD0E653EZ9FWD2SD9NNB6"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "strength must be between 0 and 1",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
Unique identifier of the source music, from a successful task's `result.music[].clip_id`
Cover editing instruction
Example: `"Rearrange this song in jazz style"`
Editing intensity
Range: `0` \~ `1`; higher values mean larger changes
Title of the covered music
Random seed, used to reproduce results
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Rearrange the whole song in jazz style
```json theme={null}
{
"model": "flowmusic",
"clip_id": "abc123-def456",
"instruction": "Rearrange this song in jazz style",
"strength": 0.5
}
```
### Scenario 2: Import external audio, then rearrange
First import external audio via [Upload Audio](./upload-audio) to obtain a clip\_id, then run the Cover:
```json theme={null}
{
"model": "flowmusic",
"clip_id": "1db3a20f-4ddc-44e8-8c9c-6c9093c16ffe",
"instruction": "Turn it into jazz style",
"strength": 0.6
}
```
**Query Task Results**
Cover rearrangement is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results. The Cover output is a **new** `clip_id`; use the new clip\_id for subsequent operations.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVD0E653EZ9FWD2SD9NNB6",
"status": "completed",
"progress": 100,
"created": 1783413244,
"completed": 1783413315,
"actual_time": 71,
"cost": 0.048,
"credits_cost": 0.48,
"result": {
"music": [
{
"clip_id": "ef3d804e-fa97-402f-ba17-4ff08270159b",
"title": "Untitled (Cover)",
"duration_seconds": "178.03733333",
"create_time": "2026-07-07T08:34:58.112190Z",
"lyrics": "[Verse 1]\nWaking up to the morning light,\n...",
"lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1",
"lyrics_timing_markers": [[10, 12], [212, 36]],
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_ef3d804e.m4a",
"wav_url": "https://cdn.apimart.ai/audio/flowmusic_ef3d804e.wav",
"image_url": "https://cdn.apimart.ai/image/flowmusic_ef3d804e_cover.jpg"
}
]
}
}
}
```
# Lyria 3.5 Cover Rearrangement
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/cover-lyria-3-5
POST https://api.apimart.ai/v1/music/generations/coverFlowMusic
Use Lyria 3.5 to rearrange the style of an entire song
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/coverFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"version": "lyria-3.5",
"clip_id": "abc123-def456",
"instruction": "Rearrange this song in jazz style",
"strength": 0.5
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/coverFlowMusic"
payload = {
"model": "flowmusic",
"version": "lyria-3.5",
"clip_id": "abc123-def456",
"instruction": "Rearrange this song in jazz style",
"strength": 0.5
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/coverFlowMusic";
const payload = {
model: "flowmusic",
version: "lyria-3.5",
clip_id: "abc123-def456",
instruction: "Rearrange this song in jazz style",
strength: 0.5
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVD0E653EZ9FWD2SD9NNB6"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "strength must be between 0 and 1",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
Model version, **must be `"lyria-3.5"`**
Lyria 3.5 still uses `flowmusic` as the model name. Do not change `model` to `lyria-3.5` or `flowmusic-lyria-3.5`.
Unique identifier of the source music, from a successful task's `result.music[].clip_id`
Cover editing instruction
Example: `"Rearrange this song in jazz style"`
Editing intensity
Range: `0` \~ `1`; higher values mean larger changes
Title of the covered music
Random seed, used to reproduce results
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Rearrange the whole song in jazz style
```json theme={null}
{
"model": "flowmusic",
"version": "lyria-3.5",
"clip_id": "abc123-def456",
"instruction": "Rearrange this song in jazz style",
"strength": 0.5
}
```
### Scenario 2: Import external audio, then rearrange
First import external audio via [Upload Audio](./upload-audio) to obtain a clip\_id, then run the Cover:
```json theme={null}
{
"model": "flowmusic",
"version": "lyria-3.5",
"clip_id": "1db3a20f-4ddc-44e8-8c9c-6c9093c16ffe",
"instruction": "Turn it into jazz style",
"strength": 0.6
}
```
**Query Task Results**
Cover rearrangement is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results. The Cover output is a **new** `clip_id`; use the new clip\_id for subsequent operations.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVD0E653EZ9FWD2SD9NNB6",
"status": "completed",
"progress": 100,
"created": 1783413244,
"completed": 1783413315,
"actual_time": 71,
"cost": 0.048,
"credits_cost": 0.48,
"result": {
"music": [
{
"clip_id": "ef3d804e-fa97-402f-ba17-4ff08270159b",
"title": "Untitled (Cover)",
"duration_seconds": "178.03733333",
"create_time": "2026-07-07T08:34:58.112190Z",
"lyrics": "[Verse 1]\nWaking up to the morning light,\n...",
"lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1",
"lyrics_timing_markers": [[10, 12], [212, 36]],
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_ef3d804e.m4a",
"wav_url": "https://cdn.apimart.ai/audio/flowmusic_ef3d804e.wav",
"image_url": "https://cdn.apimart.ai/image/flowmusic_ef3d804e_cover.jpg"
}
]
}
}
}
```
# Download Audio
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/download-audio
POST https://api.apimart.ai/v1/music/generations/downloadAudioFlowMusic
Flow Music exports a clip as an audio file in the specified format (wav / mp3)
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/downloadAudioFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"clip_id": "abc123-def456",
"format": "wav"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/downloadAudioFlowMusic"
payload = {
"model": "flowmusic",
"clip_id": "abc123-def456",
"format": "wav"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/downloadAudioFlowMusic";
const payload = {
model: "flowmusic",
clip_id: "abc123-def456",
format: "wav"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVD3FPYYQPJ2N87XXE5NQG"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "format must be one of: wav, mp3",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
clip\_id of the music to download, from a successful task's `result.music[].clip_id`
Download format
Options:
* `mp3` - Lossy compression, smaller file size
* `wav` - Lossless, suitable for post-production
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Export lossless wav
```json theme={null}
{
"model": "flowmusic",
"clip_id": "abc123-def456",
"format": "wav"
}
```
**Query Task Results**
Audio download is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results. The result is always in `result.music[0].audio_url` (`url` has the same value); the `format` / `mime_type` fields indicate the actual format.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVD3FPYYQPJ2N87XXE5NQG",
"status": "completed",
"progress": 100,
"created": 1783413247,
"completed": 1783413296,
"actual_time": 49,
"cost": 0.016,
"credits_cost": 0.16,
"result": {
"music": [
{
"clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c",
"format": "wav",
"mime_type": "audio/wav",
"size_bytes": 34900726,
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4_download_audio.wav",
"url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4_download_audio.wav"
}
]
}
}
}
```
# Query Task
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/query
GET https://api.apimart.ai/v1/music/tasks/{task_id}
Query the execution status, progress, and generated results of Flow Music asynchronous tasks
```bash cURL theme={null}
curl --request GET \
--url https://api.apimart.ai/v1/music/tasks/task_01K8AYYM6R03TGZ3Q2P0TZVNPX?language=en \
--header 'Authorization: Bearer '
```
```python Python theme={null}
import requests
task_id = "task_01K8AYYM6R03TGZ3Q2P0TZVNPX"
url = f"https://api.apimart.ai/v1/music/tasks/{task_id}"
headers = {
"Authorization": "Bearer "
}
params = {
"language": "en"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())
```
```javascript JavaScript theme={null}
const taskId = "task_01K8AYYM6R03TGZ3Q2P0TZVNPX";
const url = `https://api.apimart.ai/v1/music/tasks/${taskId}?language=en`;
const headers = {
"Authorization": "Bearer "
};
fetch(url, {
method: "GET",
headers: headers
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
```
```json 200 theme={null}
{
"code": 200,
"data": {
"id": "task_01K8AYYM6R03TGZ3Q2P0TZVNPX",
"status": "completed",
"progress": 100,
"created": 1783413241,
"completed": 1783413352,
"actual_time": 111,
"cost": 0.06,
"credits_cost": 0.6,
"result": {
"music": [
{
"clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c",
"title": "My Song",
"duration_seconds": "181.70666667",
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4.m4a",
"wav_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4.wav"
}
]
}
}
}
```
```json 404 theme={null}
{
"error": {
"message": "task not found",
"type": "invalid_request",
"param": "task_id",
"code": "task_not_found"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All Flow Music endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Path Parameters
The task ID returned after submitting a Flow Music task
The task ID comes from `data[0].task_id` in the submission response.
## Query Parameters
Language for error messages and some prompt texts
Allowed values: `zh`, `en`, `ja`, `ko`
## Response Fields
Response status code, 200 on success
Task details
Task ID
Task status: `pending`, `processing`, `completed`, `failed`
Task progress, range 0-100
Actual amount charged; usually 0 when the task fails
Credits actually consumed
Generated results after the task completes; the fields returned differ by Flow Music capability
## Result Structure
### Music Tasks
Music generation, extension, section replacement, cover rearrangement, stem separation, audio upload, audio download, and video rendering usually return a `result.music` array.
```json theme={null}
{
"result": {
"music": [
{
"clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c",
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4.m4a",
"wav_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4.wav",
"video_url": "https://cdn.apimart.ai/video/flowmusic_a41aade4.mp4",
"file_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4_stems.zip"
}
]
}
}
```
### Lyrics Tasks
Lyrics generation returns a `result.lyrics` array.
```json theme={null}
{
"result": {
"lyrics": [
{
"title": "Bleached",
"lyrics": "[Intro]\n(Check)\n(One two)\n..."
}
]
}
}
```
## Usage Notes
All Flow Music submission endpoints are asynchronous tasks. After a successful submission, first obtain the `task_id`, then call this endpoint to poll the task status; when `status` is `completed`, read the generated results from `result`.
# Replace Section
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/replace
POST https://api.apimart.ai/v1/music/generations/replaceFlowMusic
Flow Music replaces a section of previously generated audio. Regenerates the segment between start_s and end_s according to an editing instruction
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/replaceFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"clip_id": "abc123-def456",
"start_s": 10,
"end_s": 20,
"instruction": "Replace with a piano version"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/replaceFlowMusic"
payload = {
"model": "flowmusic",
"clip_id": "abc123-def456",
"start_s": 10,
"end_s": 20,
"instruction": "Replace with a piano version"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/replaceFlowMusic";
const payload = {
model: "flowmusic",
clip_id: "abc123-def456",
start_s: 10,
end_s: 20,
instruction: "Replace with a piano version"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVHGTG5JM33S8FG1K90YQ6"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "end_s must be greater than start_s",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
Source music clip\_id, from a successful task's `result.music[].clip_id`
Replacement start time (seconds)
Replacement end time (seconds)
`end_s` must be greater than `start_s` and cannot exceed the source clip's duration.
Editing instruction for the replaced section
Example: `"Replace with a piano version"`
Title of the music after replacement
Random seed, used to reproduce or control the generation result
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Replace seconds 10-20 with a piano version
```json theme={null}
{
"model": "flowmusic",
"clip_id": "abc123-def456",
"start_s": 10,
"end_s": 20,
"instruction": "Replace with a piano version"
}
```
**Query Task Results**
Section replacement is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results. The replacement output is a **new** `clip_id` (the whole song is re-rendered with the specified segment replaced); use the new clip\_id for subsequent operations.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVHGTG5JM33S8FG1K90YQ6",
"status": "completed",
"progress": 100,
"created": 1783413392,
"completed": 1783413454,
"actual_time": 62,
"cost": 0.048,
"credits_cost": 0.48,
"result": {
"music": [
{
"clip_id": "9508d1fe-633e-464b-8a40-c6368e5464fa",
"title": "Untitled (Replaced)",
"duration_seconds": "181.58933333",
"create_time": "2026-07-07T08:37:13.864452Z",
"lyrics": "[Verse 1]\nWaking up to the morning light,\n...",
"lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1",
"lyrics_timing_markers": [[10, 12], [71, 15]],
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_9508d1fe.m4a",
"wav_url": "https://cdn.apimart.ai/audio/flowmusic_9508d1fe.wav",
"image_url": "https://cdn.apimart.ai/image/flowmusic_9508d1fe_cover.jpg"
}
]
}
}
}
```
# Lyria 3.5 Replace Section
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/replace-lyria-3-5
POST https://api.apimart.ai/v1/music/generations/replaceFlowMusic
Use Lyria 3.5 to replace a specified section of previously generated audio
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/replaceFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"version": "lyria-3.5",
"clip_id": "abc123-def456",
"start_s": 10,
"end_s": 20,
"instruction": "Replace with a piano version"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/replaceFlowMusic"
payload = {
"model": "flowmusic",
"version": "lyria-3.5",
"clip_id": "abc123-def456",
"start_s": 10,
"end_s": 20,
"instruction": "Replace with a piano version"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/replaceFlowMusic";
const payload = {
model: "flowmusic",
version: "lyria-3.5",
clip_id: "abc123-def456",
start_s: 10,
end_s: 20,
instruction: "Replace with a piano version"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVHGTG5JM33S8FG1K90YQ6"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "end_s must be greater than start_s",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
Model version, **must be `"lyria-3.5"`**
Lyria 3.5 still uses `flowmusic` as the model name. Do not change `model` to `lyria-3.5` or `flowmusic-lyria-3.5`.
Source music clip\_id, from a successful task's `result.music[].clip_id`
Replacement start time (seconds)
Replacement end time (seconds)
`end_s` must be greater than `start_s` and cannot exceed the source clip's duration.
Editing instruction for the replaced section
Example: `"Replace with a piano version"`
Title of the music after replacement
Random seed, used to reproduce or control the generation result
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Replace seconds 10-20 with a piano version
```json theme={null}
{
"model": "flowmusic",
"version": "lyria-3.5",
"clip_id": "abc123-def456",
"start_s": 10,
"end_s": 20,
"instruction": "Replace with a piano version"
}
```
**Query Task Results**
Section replacement is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results. The replacement output is a **new** `clip_id` (the whole song is re-rendered with the specified segment replaced); use the new clip\_id for subsequent operations.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVHGTG5JM33S8FG1K90YQ6",
"status": "completed",
"progress": 100,
"created": 1783413392,
"completed": 1783413454,
"actual_time": 62,
"cost": 0.048,
"credits_cost": 0.48,
"result": {
"music": [
{
"clip_id": "9508d1fe-633e-464b-8a40-c6368e5464fa",
"title": "Untitled (Replaced)",
"duration_seconds": "181.58933333",
"create_time": "2026-07-07T08:37:13.864452Z",
"lyrics": "[Verse 1]\nWaking up to the morning light,\n...",
"lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1",
"lyrics_timing_markers": [[10, 12], [71, 15]],
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_9508d1fe.m4a",
"wav_url": "https://cdn.apimart.ai/audio/flowmusic_9508d1fe.wav",
"image_url": "https://cdn.apimart.ai/image/flowmusic_9508d1fe_cover.jpg"
}
]
}
}
}
```
# Stem Separation
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/stems
POST https://api.apimart.ai/v1/music/generations/stemsFlowMusic
Flow Music separates vocal / instrumental tracks, delivered as a zip stem package
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/stemsFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"clip_id": "abc123-def456"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/stemsFlowMusic"
payload = {
"model": "flowmusic",
"clip_id": "abc123-def456"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/stemsFlowMusic";
const payload = {
model: "flowmusic",
clip_id: "abc123-def456"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVD1EFXYEHDJ8M0XNJ65AR"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "clip_id is required",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
clip\_id of the music to separate, from a successful task's `result.music[].clip_id`
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Separate vocals and instrumental
```json theme={null}
{
"model": "flowmusic",
"clip_id": "abc123-def456"
}
```
**Query Task Results**
Stem separation is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results. The separation result is **a single zip archive** (`result.music[0].file_url`, about 20MB) containing the vocal / instrumental stem audio tracks, available for direct download.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVD1EFXYEHDJ8M0XNJ65AR",
"status": "completed",
"progress": 100,
"created": 1783413245,
"completed": 1783413331,
"actual_time": 86,
"cost": 0.048,
"credits_cost": 0.48,
"result": {
"music": [
{
"clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c",
"file_url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4_stems.zip",
"url": "https://cdn.apimart.ai/audio/flowmusic_a41aade4_stems.zip",
"mime_type": "application/zip",
"size_bytes": 20323367
}
]
}
}
}
```
# Upload Audio
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/upload-audio
POST https://api.apimart.ai/v1/music/generations/uploadAudioFlowMusic
Import external audio into Flow Music in exchange for a clip_id for subsequent extend / replace / cover / stem operations
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/uploadAudioFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"audio_url": "https://example.com/audio.mp3"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/uploadAudioFlowMusic"
payload = {
"model": "flowmusic",
"audio_url": "https://example.com/audio.mp3"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/uploadAudioFlowMusic";
const payload = {
model: "flowmusic",
audio_url: "https://example.com/audio.mp3"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVD2FC61SYZ5103Z4XCCS5"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "audio_url is required",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
URL of the audio file to upload; must be publicly accessible
Only common audio file extensions (such as `.mp3` / `.wav`) are supported.
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Import external audio in exchange for a clip\_id
```json theme={null}
{
"model": "flowmusic",
"audio_url": "https://example.com/audio.mp3"
}
```
Once completed, take the imported clip\_id from `result.music[0].clip_id`; it can then be used for [Extend](./extend) / [Replace](./replace) / [Cover](./cover) / [Stems](./stems).
**Query Task Results**
Audio upload is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVD2FC61SYZ5103Z4XCCS5",
"status": "completed",
"progress": 100,
"created": 1783413246,
"completed": 1783413282,
"actual_time": 36,
"cost": 0.008,
"credits_cost": 0.08,
"result": {
"music": [
{
"clip_id": "1db3a20f-4ddc-44e8-8c9c-6c9093c16ffe",
"audio_url": "https://cdn.apimart.ai/audio/flowmusic_1db3a20f_upload_audio.wav",
"url": "https://cdn.apimart.ai/audio/flowmusic_1db3a20f_upload_audio.wav"
}
]
}
}
}
```
# Music Video Rendering
Source: https://docs.apimart.ai/en/api-reference/audios/flow-music/video-clip
POST https://api.apimart.ai/v1/music/generations/videoClipFlowMusic
Flow Music renders music into an mp4 video from a template, supporting three presets: simple / modern / player
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/videoClipFlowMusic \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "flowmusic",
"clip_id": "abc123-def456",
"preset": "modern"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/videoClipFlowMusic"
payload = {
"model": "flowmusic",
"clip_id": "abc123-def456",
"preset": "modern"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/videoClipFlowMusic";
const payload = {
model: "flowmusic",
clip_id: "abc123-def456",
preset: "modern"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KWXVD4HQEEY7B5NJ31177Q1H"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "clip_id is required",
"type": "invalid_request",
"param": "",
"code": "invalid_request"
}
}
```
```json 403 theme={null}
{
"error": {
"message": "Insufficient balance",
"type": "invalid_request",
"param": "",
"code": "quota_not_enough"
}
}
```
```json 429 theme={null}
{
"error": {
"message": "Current group capacity is saturated, please retry later",
"type": "rate_limit_error",
"param": "",
"code": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Request Parameters
Model name, **must be `"flowmusic"`** (case-insensitive)
clip\_id of the music to generate a video for, from a successful task's `result.music[].clip_id`
Video template preset
Options:
* `simple` - Clean template
* `modern` - Modern-style template
* `player` - Player-style template
## Response
Response status code, 200 on success
Array of returned data
Task status, `submitted` upon initial submission
Unique task identifier, used to query task status and results
## Use Cases
### Scenario 1: Render a music video with the modern template
```json theme={null}
{
"model": "flowmusic",
"clip_id": "abc123-def456",
"preset": "modern"
}
```
**Query Task Results**
Music video rendering is an asynchronous task; a `task_id` is returned after submission. Use the [Get Task Status](./query) endpoint to query generation progress and results. The result is in `result.music[0].video_url`.
## Completed Task Result Example
**Query response example** (`GET /v1/music/tasks/{task_id}`):
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01KWXVD4HQEEY7B5NJ31177Q1H",
"status": "completed",
"progress": 100,
"created": 1783413248,
"completed": 1783413327,
"actual_time": 79,
"cost": 0.016,
"credits_cost": 0.16,
"result": {
"music": [
{
"clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c",
"video_url": "https://cdn.apimart.ai/video/flowmusic_a41aade4_video_clip.mp4",
"url": "https://cdn.apimart.ai/video/flowmusic_a41aade4_video_clip.mp4"
}
]
}
}
}
```
# Add accompaniment
Source: https://docs.apimart.ai/en/api-reference/audios/suno/add-instrumental
POST https://api.apimart.ai/v1/music/generations/addInstrumental
- Layer accompaniment onto an existing (vocals / track).
- Source track must be your own track uploaded via `uploadTask`: pass that upload task's `task_id` + `audio_index`; using a generated track as the source will fail
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing the source track**: The source must be your own audio uploaded via `uploadTask`; pass that upload task's `task_id` + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`). **Using a generated track as the source will fail**—you can only reference tracks you uploaded yourself.
`custom` determines which fields take effect: fields written under the wrong mode are **silently ignored** (no error). With `custom=true`, `prompt` (lyrics), `title`, `tags`, `negative_tags`, `style_weight`, `weirdness_constraint`, and `audio_weight` take effect and `gpt_description` is ignored; with `custom=false`, only `gpt_description` is read (**required** in that case — if missing, a 400 is returned at submission time). `vocal_gender` works in both modes. If `custom` is omitted, the backend infers it in this order: `prompt` present → `true`; no `prompt` but `gpt_description` present → `false`; otherwise `tags`/`title` present → `true`.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/addInstrumental \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "lo-fi"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/addInstrumental"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "lo-fi"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/addInstrumental";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
version: "v5",
tags: "lo-fi"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/addInstrumental"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "lo-fi",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/addInstrumental";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "lo-fi"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"version" => "v5",
"tags" => "lo-fi"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/addInstrumental")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
version: "v5",
tags: "lo-fi"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/addInstrumental")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "lo-fi"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/addInstrumental";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""version"": ""v5"",
""tags"": ""lo-fi""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/addInstrumental";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"version\":\"v5\","
"\"tags\":\"lo-fi\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/addInstrumental"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"version": @"v5",
@"tags": @"lo-fi"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/addInstrumental"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "lo-fi"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/addInstrumental');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'version': 'v5',
'tags': 'lo-fi'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/addInstrumental"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
version = "v5",
tags = "lo-fi"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
The `task_id` of the `uploadTask` upload that holds the source track (must be a track you uploaded yourself; using a track from a generation task as the source will fail). If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Generation version: **only `v5` / `v5.5`**; defaults to `v5.5` if omitted. Any other value returns `400` directly at submission time.
`true`=custom mode (`prompt` used as lyrics); `false`=inspiration mode (uses `gpt_description`); if omitted, inferred from the content (see the Warning above).
Lyrics. Takes effect when `custom=true` (ignored in inspiration mode).
Inspiration prompt. **Required when `custom=false`** — if missing, the request fails with `400` at submission (nothing is charged).
Title. **Only takes effect when `custom=true`**.
Style tags. **Only takes effect when `custom=true`**.
Style tags to exclude. **Only takes effect when `custom=true`**.
Style weight, `0.00`–`1.00` (out-of-range values return `400` directly at submission time). **Only takes effect when `custom=true`**.
Creativity weight, `0.00`–`1.00` (alias `weirdness`). **Only takes effect when `custom=true`**.
Audio weight, `0.00`–`1.00`. **Only takes effect when `custom=true`**.
Vocal gender: `Male` / `Female`. **Works in both modes**.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Add stem (add stem)
Source: https://docs.apimart.ai/en/api-reference/audios/suno/add-stem
POST https://api.apimart.ai/v1/music/generations/addStem
- Layer a stem onto an existing track.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
`custom` determines which fields take effect: fields written under the wrong mode are **silently ignored** (no error). With `custom=true`, `prompt` (lyrics), `title`, `tags`, `negative_tags`, `style_weight`, `weirdness_constraint`, and `audio_weight` take effect and `gpt_description` is ignored; with `custom=false`, only `gpt_description` is read (**required** in that case — if missing, a 400 is returned at submission time). If `custom` is omitted, the backend infers it in this order: `prompt` present → `true`; no `prompt` but `gpt_description` present → `false`; otherwise `tags`/`title` present → `true`.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/addStem \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5.5"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/addStem"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5.5"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/addStem";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
version: "v5.5"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/addStem"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5.5",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/addStem";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5.5"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"version" => "v5.5"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/addStem")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
version: "v5.5"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/addStem")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5.5"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/addStem";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""version"": ""v5.5""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/addStem";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"version\":\"v5.5\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/addStem"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"version": @"v5.5"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/addStem"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5.5"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/addStem');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'version': 'v5.5'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/addStem"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
version = "v5.5"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Generation version: **`v5.5` only**; defaults to `v5.5` if omitted. Any other value returns `400` directly at submission time (`v3.5` / `v4` error out; `v4.5` / `v5` would stall at 10% until the job times out).
`true`=custom mode (`prompt` used as lyrics); `false`=inspiration mode (uses `gpt_description`); if omitted, inferred from the content (see the Warning above).
Lyrics. Takes effect when `custom=true` (ignored in inspiration mode).
Inspiration prompt. **Required when `custom=false`** — if missing, the request fails with `400` at submission (nothing is charged).
Title. **Only takes effect when `custom=true`**.
Style tags. **Only takes effect when `custom=true`**.
Style tags to exclude. **Only takes effect when `custom=true`**.
Style weight, `0.00`–`1.00` (out-of-range values return `400` directly at submission time). **Only takes effect when `custom=true`**.
Creativity weight, `0.00`–`1.00` (alias `weirdness`). **Only takes effect when `custom=true`**.
Audio weight, `0.00`–`1.00`. **Only takes effect when `custom=true`**.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Add vocals
Source: https://docs.apimart.ai/en/api-reference/audios/suno/add-vocals
POST https://api.apimart.ai/v1/music/generations/addVocals
- Layer vocals onto an existing (accompaniment / track).
- Source track must be your own track uploaded via `uploadTask`: pass that upload task's `task_id` + `audio_index`; using a generated track as the source will fail
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing the source track**: The source must be your own audio uploaded via `uploadTask`; pass that upload task's `task_id` + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`). **Using a generated track as the source will fail**—you can only reference tracks you uploaded yourself.
`custom` determines which fields take effect: fields written under the wrong mode are **silently ignored** (no error). With `custom=true`, `prompt` (lyrics), `title`, `tags`, `negative_tags`, `style_weight`, `weirdness_constraint`, and `audio_weight` take effect and `gpt_description` is ignored; with `custom=false`, only `gpt_description` is read (**required** in that case — if missing, a 400 is returned at submission time). `vocal_gender` works in both modes. If `custom` is omitted, the backend infers it in this order: `prompt` present → `true`; no `prompt` but `gpt_description` present → `false`; otherwise `tags`/`title` present → `true`.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/addVocals \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"custom": true,
"prompt": "…lyrics…"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/addVocals"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"custom": True,
"prompt": "…lyrics…"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/addVocals";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
version: "v5",
custom: true,
prompt: "…lyrics…"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/addVocals"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"custom": true,
"prompt": "…lyrics…",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/addVocals";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"custom": true,
"prompt": "…lyrics…"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"version" => "v5",
"custom" => true,
"prompt" => "…lyrics…"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/addVocals")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
version: "v5",
custom: true,
prompt: "…lyrics…"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/addVocals")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"custom": true,
"prompt": "…lyrics…"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/addVocals";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""version"": ""v5"",
""custom"": true,
""prompt"": ""…lyrics…""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/addVocals";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"version\":\"v5\","
"\"custom\":true,"
"\"prompt\":\"…lyrics…\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/addVocals"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"version": @"v5",
@"custom": @YES,
@"prompt": @"…lyrics…"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/addVocals"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"custom": true,
"prompt": "…lyrics…"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/addVocals');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'version': 'v5',
'custom': true,
'prompt': '…lyrics…'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/addVocals"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
version = "v5",
custom = TRUE,
prompt = "…lyrics…"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
The `task_id` of the `uploadTask` upload that holds the source track (must be a track you uploaded yourself; using a track from a generation task as the source will fail). If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Generation version: **only `v5` / `v5.5`**; defaults to `v5.5` if omitted. Any other value returns `400` directly at submission time.
`true`=custom mode (`prompt` used as lyrics); `false`=inspiration mode (uses `gpt_description`); if omitted, inferred from the content (see the Warning above).
Lyrics. Takes effect when `custom=true` (ignored in inspiration mode).
Inspiration prompt. **Required when `custom=false`** — if missing, the request fails with `400` at submission (nothing is charged).
Title. **Only takes effect when `custom=true`**.
Style tags. **Only takes effect when `custom=true`**.
Style tags to exclude. **Only takes effect when `custom=true`**.
Style weight, `0.00`–`1.00` (out-of-range values return `400` directly at submission time). **Only takes effect when `custom=true`**.
Creativity weight, `0.00`–`1.00` (alias `weirdness`). **Only takes effect when `custom=true`**.
Audio weight, `0.00`–`1.00`. **Only takes effect when `custom=true`**.
Vocal gender: `Male` / `Female`. **Works in both modes**.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Adjust speed
Source: https://docs.apimart.ai/en/api-reference/audios/suno/adjust-speed
POST https://api.apimart.ai/v1/music/generations/adjustSpeed
- Change speed (without changing pitch).
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/adjustSpeed \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"speed": 1.25
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/adjustSpeed"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"speed": 1.25
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/adjustSpeed";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
speed: 1.25
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/adjustSpeed"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"speed": 1.25,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/adjustSpeed";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"speed": 1.25
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"speed" => 1.25
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/adjustSpeed")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
speed: 1.25
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/adjustSpeed")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"speed": 1.25
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/adjustSpeed";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""speed"": 1.25
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/adjustSpeed";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"speed\":1.25"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/adjustSpeed"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"speed": @1.25
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/adjustSpeed"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"speed": 1.25
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/adjustSpeed');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'speed': 1.25
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/adjustSpeed"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
speed = 1.25
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Speed multiplier, range `0.25`–`4`, e.g. `1.25`. Missing or out-of-range values return `400` directly at submission time.
Whether to keep the original pitch when changing speed (defaults to `true`).
Title (defaults to `Untitled`).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take the processed `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Lyrics timeline
Source: https://docs.apimart.ai/en/api-reference/audios/suno/aligned-lyrics
POST https://api.apimart.ai/v1/music/generations/alignedLyrics
- Generate a line-by-line aligned lyrics timeline.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/alignedLyrics \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/alignedLyrics"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/alignedLyrics";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/alignedLyrics"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/alignedLyrics";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/alignedLyrics")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/alignedLyrics")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/alignedLyrics";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/alignedLyrics";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/alignedLyrics"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/alignedLyrics"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/alignedLyrics');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/alignedLyrics"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). The result contains timestamped lyrics. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# BPM analysis
Source: https://docs.apimart.ai/en/api-reference/audios/suno/bpm
POST https://api.apimart.ai/v1/music/generations/bpm
- Analyze a song's BPM.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/bpm \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/bpm"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/bpm";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/bpm"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/bpm";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/bpm")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/bpm")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/bpm";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/bpm";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/bpm"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/bpm"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/bpm');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/bpm"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). The result contains the BPM value. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Full song synthesis / concatenation
Source: https://docs.apimart.ai/en/api-reference/audios/suno/concat
POST https://api.apimart.ai/v1/music/generations/concat
- Synthesize segments into a complete song.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
**Prerequisite**: `concat` can only join **segments produced by extend (continuation)**. If the source is not an extend product (e.g. a normal one-shot full song), the request is rejected at submission with a `400`.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/concat \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/concat"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/concat";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/concat"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/concat";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/concat")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/concat")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/concat";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/concat";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/concat"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/concat"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/concat');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/concat"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the source job — **must be a segment produced by extend (continuation)** (see the Warning above). If missing, not an extend product, or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take the full song `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Style cover
Source: https://docs.apimart.ai/en/api-reference/audios/suno/cover-song
POST https://api.apimart.ai/v1/music/generations/coverSong
- Cover an existing song in a different style.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
`custom` determines which fields take effect: fields written under the wrong mode are **silently ignored** (no error). With `custom=true`, `prompt` (lyrics), `title`, `tags`, `negative_tags`, `style_weight`, `weirdness_constraint`, `audio_weight`, and `persona_id` take effect and `gpt_description` is ignored; with `custom=false`, only `gpt_description` is read (**required** in that case — if missing, a 400 is returned at submission time). `vocal_gender` works in both modes. If `custom` is omitted, the backend infers it in this order: `prompt` present → `true`; no `prompt` but `gpt_description` present → `false`; otherwise `tags`/`title` present → `true`.
## Usage
**Usage A — cover in a specified style (most common, recommended)**
Provide the source song + target style `tags`; no need to worry about `custom` (when the system sees `tags` it automatically treats it as `custom=true`):
```json theme={null}
{
"model": "suno",
"task_id": "task_xxx", // source song: a completed music task
"audio_index": 1, // which track in the source job (1-based, defaults to 1)
"version": "v5",
"tags": "jazz, slow" // target style → automatically custom=true
}
```
For more control you can also add `prompt` (lyrics) / `title`.
**Usage B — inspiration mode (`custom=false`)**
Don't specify a concrete style and let the model improvise, but you must provide `gpt_description` describing the effect you want:
```json theme={null}
{
"model": "suno",
"task_id": "task_xxx",
"audio_index": 1,
"version": "v5",
"custom": false,
"gpt_description": "Cover this song in a slow jazz style" // required when custom=false
}
```
Pick one of the two usages — don't pass only `custom=false` without `gpt_description` (that fails with `400` at submission).
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/coverSong \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "jazz, slow"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/coverSong"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "jazz, slow"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/coverSong";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
version: "v5",
tags: "jazz, slow"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/coverSong"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "jazz, slow",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/coverSong";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "jazz, slow"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"version" => "v5",
"tags" => "jazz, slow"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/coverSong")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
version: "v5",
tags: "jazz, slow"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/coverSong")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "jazz, slow"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/coverSong";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""version"": ""v5"",
""tags"": ""jazz, slow""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/coverSong";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"version\":\"v5\","
"\"tags\":\"jazz, slow\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/coverSong"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"version": @"v5",
@"tags": @"jazz, slow"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/coverSong"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
"tags": "jazz, slow"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/coverSong');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'version': 'v5',
'tags': 'jazz, slow'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/coverSong"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
version = "v5",
tags = "jazz, slow"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based: 1 = first track; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Generation version: `v3.5` / `v4` / `v4.5` / `v4.5+` / `v4.5-all` / `v5` / `v5.5`, affects audio quality and billing; defaults to `v5.5` if omitted, and an invalid value returns `400` directly at submission time.
`true`=custom mode (`prompt` used as lyrics); `false`=inspiration mode (uses `gpt_description`); if omitted, inferred from the content (see the Warning above).
Lyrics. Takes effect when `custom=true` (ignored in inspiration mode).
Inspiration prompt. **Required when `custom=false`** — if missing, the request fails with `400` at submission (nothing is charged).
Title. **Only takes effect when `custom=true`**.
Target style tags. **Only takes effect when `custom=true`**.
Style tags to exclude. **Only takes effect when `custom=true`**.
Style weight, `0.00`–`1.00` (out-of-range values return `400` directly at submission time). **Only takes effect when `custom=true`**.
Creativity weight, `0.00`–`1.00` (alias `weirdness`). **Only takes effect when `custom=true`**.
Audio weight, `0.00`–`1.00`. **Only takes effect when `custom=true`**.
Vocal gender: `Male` / `Female`. **Works in both modes**.
Persona style id. **Only takes effect when `custom=true`**.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Create voice
Source: https://docs.apimart.ai/en/api-reference/audios/suno/create-voice
POST https://api.apimart.ai/v1/music/generations/createVoice
- Create a reusable voice from a track.
- Referencing the source track: this endpoint does NOT use `task_id` + `audio_index` — provide a publicly accessible `audio_url` directly
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing the source track**: this endpoint does **not** use `task_id` + `audio_index`; you must directly provide a publicly accessible `audio_url` (the system extracts the voice from it). If missing, returns 400 `audio_url cannot be empty`.
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/createVoice \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"audio_url": "https://example.com/source.mp3"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/createVoice"
payload = {
"model": "suno",
"audio_url": "https://example.com/source.mp3"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/createVoice";
const payload = {
model: "suno",
audio_url: "https://example.com/source.mp3"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/createVoice"
payload := map[string]interface{}{
"model": "suno",
"audio_url": "https://example.com/source.mp3",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/createVoice";
String payload = """
{
"model": "suno",
"audio_url": "https://example.com/source.mp3"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"audio_url" => "https://example.com/source.mp3"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/createVoice")
payload = {
model: "suno",
audio_url: "https://example.com/source.mp3"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/createVoice")!
let payload: [String: Any] = [
"model": "suno",
"audio_url": "https://example.com/source.mp3"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/createVoice";
var payload = @"{
""model"": ""suno"",
""audio_url"": ""https://example.com/source.mp3""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/createVoice";
const char *payload = "{"
"\"model\":\"suno\","
"\"audio_url\":\"https://example.com/source.mp3\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/createVoice"];
NSDictionary *payload = @{
@"model": @"suno",
@"audio_url": @"https://example.com/source.mp3"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/createVoice"
let payload = {|{
"model": "suno",
"audio_url": "https://example.com/source.mp3"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/createVoice');
final payload = {
'model': 'suno',
'audio_url': 'https://example.com/source.mp3'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/createVoice"
payload <- list(
model = "suno",
audio_url = "https://example.com/source.mp3"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Publicly accessible URL of the source track; the system extracts the voice from it. **Only MP3 / WAV are accepted.** If missing, returns 400 `audio_url cannot be empty`.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). The result contains the created voice information. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Crop audio
Source: https://docs.apimart.ai/en/api-reference/audios/suno/crop
POST https://api.apimart.ai/v1/music/generations/crop
- Crop to keep the specified range.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/crop \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 10,
"end_s": 40
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/crop"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 10,
"end_s": 40
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/crop";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
start_s: 10,
end_s: 40
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/crop"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 10,
"end_s": 40,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/crop";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 10,
"end_s": 40
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"start_s" => 10,
"end_s" => 40
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/crop")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
start_s: 10,
end_s: 40
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/crop")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 10,
"end_s": 40
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/crop";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""start_s"": 10,
""end_s"": 40
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/crop";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"start_s\":10,"
"\"end_s\":40"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/crop"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"start_s": @10,
@"end_s": @40
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/crop"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 10,
"end_s": 40
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/crop');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'start_s': 10,
'end_s': 40
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/crop"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
start_s = 10,
end_s = 40
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Crop start point (seconds). If missing, returns `400` immediately.
Crop end point (seconds). If missing, returns `400` immediately.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take the cropped `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Continuation and extension
Source: https://docs.apimart.ai/en/api-reference/audios/suno/extend
POST https://api.apimart.ai/v1/music/generations/extend
- Continue and extend an existing song from a given point in time.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
`custom` is neither required nor inferred for extend — omit it and the extension works fine; if passed, it is forwarded as-is. `custom=true` extends following the `prompt` lyrics; with `custom=false` or omitted you can pass `gpt_description` (inspiration prompt) to guide the direction.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/extend \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"continue_at": 120,
"version": "v5",
"prompt": "Continue the lyrics…"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/extend"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"continue_at": 120,
"version": "v5",
"prompt": "Continue the lyrics…"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/extend";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
continue_at: 120,
version: "v5",
prompt: "Continue the lyrics…"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/extend"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"continue_at": 120,
"version": "v5",
"prompt": "Continue the lyrics…",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/extend";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"continue_at": 120,
"version": "v5",
"prompt": "Continue the lyrics…"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"continue_at" => 120,
"version" => "v5",
"prompt" => "Continue the lyrics…"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/extend")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
continue_at: 120,
version: "v5",
prompt: "Continue the lyrics…"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/extend")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"continue_at": 120,
"version": "v5",
"prompt": "Continue the lyrics…"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/extend";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""continue_at"": 120,
""version"": ""v5"",
""prompt"": ""Continue the lyrics…""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/extend";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"continue_at\":120,"
"\"version\":\"v5\","
"\"prompt\":\"Continue the lyrics…\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/extend"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"continue_at": @120,
@"version": @"v5",
@"prompt": @"Continue the lyrics…"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/extend"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"continue_at": 120,
"version": "v5",
"prompt": "Continue the lyrics…"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/extend');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'continue_at': 120,
'version': 'v5',
'prompt': 'Continue the lyrics…'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/extend"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
continue_at = 120,
version = "v5",
prompt = "Continue the lyrics…"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
The second from which to continue.
Generation version: `v3.5` / `v4` / `v4.5` / `v4.5+` / `v4.5-all` / `v5` / `v5.5`, affects audio quality and billing; defaults to `v5.5` if omitted, and an invalid value returns `400` directly at submission time.
No need to pass it (not enforced for extend). `true`=extend following the `prompt` lyrics; `false`=inspiration-guided extension.
Lyrics for the extension. Takes effect when `custom=true`.
Inspiration prompt. Takes effect when `custom=false` or when `custom` is omitted (guides the direction of the extension).
Title. **Only takes effect when `custom=true`**.
Style tags. **Only takes effect when `custom=true`**.
Style tags to exclude. **Only takes effect when `custom=true`**.
Vocal gender: `Male` / `Female`. **Works in both modes**.
Style weight, `0.00`–`1.00` (out-of-range values return `400` directly at submission time). **Only takes effect when `custom=true`**.
Creativity weight, `0.00`–`1.00` (alias `weirdness`). **Only takes effect when `custom=true`**.
Audio weight, `0.00`–`1.00`. **Only takes effect when `custom=true`**.
`true`=rewrite the provided lyrics creatively. **Only takes effect when `custom=true`**.
Persona style id. **Only takes effect when `custom=true`**.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take the extended `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Fade in
Source: https://docs.apimart.ai/en/api-reference/audios/suno/fade-in
POST https://api.apimart.ai/v1/music/generations/fadeIn
- Fade in at the beginning.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/fadeIn \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/fadeIn"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/fadeIn";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
duration_s: 3
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/fadeIn"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/fadeIn";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"duration_s" => 3
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/fadeIn")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
duration_s: 3
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/fadeIn")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/fadeIn";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""duration_s"": 3
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/fadeIn";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"duration_s\":3"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/fadeIn"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"duration_s": @3
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/fadeIn"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/fadeIn');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'duration_s': 3
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/fadeIn"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
duration_s = 3
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Fade-in duration (seconds). If missing, returns `400` immediately.
Title (defaults to `Untitled`).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take the processed `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Fade out
Source: https://docs.apimart.ai/en/api-reference/audios/suno/fade-out
POST https://api.apimart.ai/v1/music/generations/fadeOut
- Fade out at the end.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/fadeOut \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/fadeOut"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/fadeOut";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
duration_s: 3
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/fadeOut"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/fadeOut";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"duration_s" => 3
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/fadeOut")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
duration_s: 3
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/fadeOut")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/fadeOut";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""duration_s"": 3
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/fadeOut";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"duration_s\":3"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/fadeOut"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"duration_s": @3
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/fadeOut"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"duration_s": 3
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/fadeOut');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'duration_s': 3
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/fadeOut"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
duration_s = 3
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Fade-out duration (seconds). If missing, returns `400` immediately.
Title (defaults to `Untitled`).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take the processed `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Generate music video (MV)
Source: https://docs.apimart.ai/en/api-reference/audios/suno/generate-mp4
POST https://api.apimart.ai/v1/music/generations/generateMp4
- Generate an MV video for the song.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/generateMp4 \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/generateMp4"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/generateMp4";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/generateMp4"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/generateMp4";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/generateMp4")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/generateMp4")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/generateMp4";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/generateMp4";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/generateMp4"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/generateMp4"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/generateMp4');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/generateMp4"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take `video_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Generate music
Source: https://docs.apimart.ai/en/api-reference/audios/suno/generation
POST https://api.apimart.ai/v1/music/generations
- Generate a song from a prompt: `custom=false` is inspiration mode (`prompt` used as an inspiration prompt), `=true` is custom mode (`prompt` used as lyrics).
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
`custom` determines which fields take effect: fields written under the wrong mode are **silently ignored** (no error). With `custom=true` (custom), `prompt` (lyrics), `title`, `style`, `negative_tags`, `auto_lyrics`, `persona_id`, `style_weight`, `weirdness_constraint`, and `audio_weight` take effect; with `custom=false` (inspiration), `prompt` is used as the inspiration description, and `title`/`style` and the custom fields above are ignored. `vocal_gender` works in both modes.
This endpoint uses a separate route, so some field names differ from other endpoints: `style` (not `tags`).
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"custom": false,
"version": "v5",
"prompt": "Late-night city lo-fi piano with the sound of rain"
}'
```
```bash cURL (Custom mode) theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"version": "v4.5+",
"custom": true,
"instrumental": false,
"prompt": "[Verse]\nNeon-lit streets on a rainy night",
"title": "Midnight Drive",
"style": "synthwave, female vocal, cinematic",
"negative_tags": "metal, screaming",
"auto_lyrics": false,
"vocal_gender": "Female",
"style_weight": 0.6,
"weirdness_constraint": 0.3,
"audio_weight": 0.5
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations"
payload = {
"model": "suno",
"custom": False,
"version": "v5",
"prompt": "Late-night city lo-fi piano with the sound of rain"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations";
const payload = {
model: "suno",
custom: false,
version: "v5",
prompt: "Late-night city lo-fi piano with the sound of rain"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations"
payload := map[string]interface{}{
"model": "suno",
"custom": false,
"version": "v5",
"prompt": "Late-night city lo-fi piano with the sound of rain",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations";
String payload = """
{
"model": "suno",
"custom": false,
"version": "v5",
"prompt": "Late-night city lo-fi piano with the sound of rain"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"custom" => false,
"version" => "v5",
"prompt" => "Late-night city lo-fi piano with the sound of rain"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations")
payload = {
model: "suno",
custom: false,
version: "v5",
prompt: "Late-night city lo-fi piano with the sound of rain"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations")!
let payload: [String: Any] = [
"model": "suno",
"custom": false,
"version": "v5",
"prompt": "Late-night city lo-fi piano with the sound of rain"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations";
var payload = @"{
""model"": ""suno"",
""custom"": false,
""version"": ""v5"",
""prompt"": ""Late-night city lo-fi piano with the sound of rain""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations";
const char *payload = "{"
"\"model\":\"suno\","
"\"custom\":false,"
"\"version\":\"v5\","
"\"prompt\":\"Late-night city lo-fi piano with the sound of rain\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations"];
NSDictionary *payload = @{
@"model": @"suno",
@"custom": @NO,
@"version": @"v5",
@"prompt": @"Late-night city lo-fi piano with the sound of rain"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations"
let payload = {|{
"model": "suno",
"custom": false,
"version": "v5",
"prompt": "Late-night city lo-fi piano with the sound of rain"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations');
final payload = {
'model': 'suno',
'custom': false,
'version': 'v5',
'prompt': 'Late-night city lo-fi piano with the sound of rain'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations"
payload <- list(
model = "suno",
custom = FALSE,
version = "v5",
prompt = "Late-night city lo-fi piano with the sound of rain"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
`false`=inspiration mode; `true`=custom mode (`prompt` used as lyrics). Defaults to `false`.
`true`=instrumental only, no vocals. Defaults to `false`.
Generation version: `v3.5` / `v4` / `v4.5` / `v4.5+` / `v4.5-all` / `v5` / `v5.5`, affects audio quality and billing. **Required in both modes; omitting it returns 400 directly**.
Inspiration prompt / lyrics. **Required when `custom=false`** (used as the inspiration description). When `custom=true`: **required** if `instrumental=false` (used as lyrics); optional if `instrumental=true`. If missing, a 400 is returned at submission time (no charge).
Title (custom mode). **Ignored when `custom=false`** (inspiration mode).
Style tags (custom mode). **Ignored when `custom=false`** (inspiration mode).
Negative style tags (styles you don't want). **Only takes effect when `custom=true`**.
`true`=rewrite the provided lyrics creatively. **Only takes effect when `custom=true`**.
Persona style id. **Only takes effect when `custom=true`**.
Vocal gender: `Male` / `Female` (`m` / `f` / `male` / `female` are also accepted and normalized by the backend). **Works in both modes**.
Style weight, `0.00`–`1.00`. **Only takes effect when `custom=true`**.
Creativity, `0.00`–`1.00`. **Only takes effect when `custom=true`**.
Audio weight, `0.00`–`1.00`. **Only takes effect when `custom=true`**.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take `audio_url` from `data.result.music[]` (also `image_url` / `video_url` / `title` / `duration`, etc.). On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Inspiration generation (inspo)
Source: https://docs.apimart.ai/en/api-reference/audios/suno/inspo
POST https://api.apimart.ai/v1/music/generations/inspo
- Generate a new song using 1–4 pieces of public audio as inspiration references (pass the audio URLs directly, not via task_id).
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/inspo \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"audio_urls": [
"https://a/1.mp3",
"https://a/2.mp3"
],
"version": "v5",
"tags": "dreamy pop"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/inspo"
payload = {
"model": "suno",
"audio_urls": ["https://a/1.mp3", "https://a/2.mp3"],
"version": "v5",
"tags": "dreamy pop"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/inspo";
const payload = {
model: "suno",
audio_urls: ["https://a/1.mp3", "https://a/2.mp3"],
version: "v5",
tags: "dreamy pop"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/inspo"
payload := map[string]interface{}{
"model": "suno",
"audio_urls": []string{"https://a/1.mp3", "https://a/2.mp3"},
"version": "v5",
"tags": "dreamy pop",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/inspo";
String payload = """
{
"model": "suno",
"audio_urls": [
"https://a/1.mp3",
"https://a/2.mp3"
],
"version": "v5",
"tags": "dreamy pop"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"audio_urls" => ["https://a/1.mp3", "https://a/2.mp3"],
"version" => "v5",
"tags" => "dreamy pop"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/inspo")
payload = {
model: "suno",
audio_urls: ["https://a/1.mp3", "https://a/2.mp3"],
version: "v5",
tags: "dreamy pop"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/inspo")!
let payload: [String: Any] = [
"model": "suno",
"audio_urls": ["https://a/1.mp3", "https://a/2.mp3"],
"version": "v5",
"tags": "dreamy pop"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/inspo";
var payload = @"{
""model"": ""suno"",
""audio_urls"": [
""https://a/1.mp3"",
""https://a/2.mp3""
],
""version"": ""v5"",
""tags"": ""dreamy pop""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/inspo";
const char *payload = "{"
"\"model\":\"suno\","
"\"audio_urls\":[\"https://a/1.mp3\",\"https://a/2.mp3\"],"
"\"version\":\"v5\","
"\"tags\":\"dreamy pop\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/inspo"];
NSDictionary *payload = @{
@"model": @"suno",
@"audio_urls": @[@"https://a/1.mp3", @"https://a/2.mp3"],
@"version": @"v5",
@"tags": @"dreamy pop"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/inspo"
let payload = {|{
"model": "suno",
"audio_urls": [
"https://a/1.mp3",
"https://a/2.mp3"
],
"version": "v5",
"tags": "dreamy pop"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/inspo');
final payload = {
'model': 'suno',
'audio_urls': ['https://a/1.mp3', 'https://a/2.mp3'],
'version': 'v5',
'tags': 'dreamy pop'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/inspo"
payload <- list(
model = "suno",
audio_urls = c("https://a/1.mp3", "https://a/2.mp3"),
version = "v5",
tags = "dreamy pop"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
An array of 1–4 publicly accessible audio URLs.
Generation version: `v4` / `v4.5` / `v4.5+` / `v4.5-all` / `v5` / `v5.5`, affects audio quality and billing; defaults to `v5.5` if omitted.
Lyrics / content.
Title.
Style tags.
Style tags to exclude.
Style weight, `0.00`–`1.00`.
Creativity weight, `0.00`–`1.00` (alias `weirdness`).
Audio weight, `0.00`–`1.00`.
Vocal gender: `Male` / `Female`.
`true`=rewrite the provided lyrics creatively.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Generate lyrics
Source: https://docs.apimart.ai/en/api-reference/audios/suno/lyrics
POST https://api.apimart.ai/v1/music/generations/lyrics
- Generate lyrics text based on a theme.
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/lyrics \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"prompt": "A heartfelt ballad about a reunion"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/lyrics"
payload = {
"model": "suno",
"prompt": "A heartfelt ballad about a reunion"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/lyrics";
const payload = {
model: "suno",
prompt: "A heartfelt ballad about a reunion"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/lyrics"
payload := map[string]interface{}{
"model": "suno",
"prompt": "A heartfelt ballad about a reunion",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/lyrics";
String payload = """
{
"model": "suno",
"prompt": "A heartfelt ballad about a reunion"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"prompt" => "A heartfelt ballad about a reunion"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/lyrics")
payload = {
model: "suno",
prompt: "A heartfelt ballad about a reunion"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/lyrics")!
let payload: [String: Any] = [
"model": "suno",
"prompt": "A heartfelt ballad about a reunion"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/lyrics";
var payload = @"{
""model"": ""suno"",
""prompt"": ""A heartfelt ballad about a reunion""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/lyrics";
const char *payload = "{"
"\"model\":\"suno\","
"\"prompt\":\"A heartfelt ballad about a reunion\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/lyrics"];
NSDictionary *payload = @{
@"model": @"suno",
@"prompt": @"A heartfelt ballad about a reunion"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/lyrics"
let payload = {|{
"model": "suno",
"prompt": "A heartfelt ballad about a reunion"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/lyrics');
final payload = {
'model': 'suno',
'prompt': 'A heartfelt ballad about a reunion'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/lyrics"
payload <- list(
model = "suno",
prompt = "A heartfelt ballad about a reunion"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Lyrics / content.
Lyrics model: `classic` / `remi` (passed through; if omitted, the default is used).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion the result contains the generated lyrics text. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Generate mashup (mashup)
Source: https://docs.apimart.ai/en/api-reference/audios/suno/mashup
POST https://api.apimart.ai/v1/music/generations/mashup
- Remix a song into a new creation.
- Referencing source tracks: requires **exactly 2**, specified via `task_ids` (an array of length 2) + optional `audio_indexes`
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing source tracks**: mashup requires **exactly 2 source tracks**—specify them via `task_ids` (an array of exactly 2 of ythe `task_id`s), with optional `audio_indexes` (a parallel array selecting which item in each task's `music[]`, 1-based, default `1` for both).
`custom` determines which fields take effect: fields written under the wrong mode are **silently ignored** (no error). With `custom=true`, `prompt` (lyrics), `title`, `tags`, `negative_tags`, `auto_lyrics`, `style_weight`, `weirdness_constraint`, `audio_weight`, and `persona_id` take effect and `gpt_description` is ignored; with `custom=false`, only `gpt_description` is read (**required** in that case — if missing, a 400 is returned at submission time). `vocal_gender` works in both modes. If `custom` is omitted, the backend infers it in this order: `prompt` present → `true`; no `prompt` but `gpt_description` present → `false`; otherwise `tags`/`title` present → `true`.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/mashup \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_ids": ["task_01ABC", "task_01DEF"],
"audio_indexes": [1, 2],
"custom": true,
"prompt": "upbeat mashup of the two tracks"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/mashup"
payload = {
"model": "suno",
"task_ids": ["task_01ABC", "task_01DEF"],
"audio_indexes": [1, 2],
"custom": True,
"prompt": "upbeat mashup of the two tracks"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/mashup";
const payload = {
model: "suno",
task_ids: ["task_01ABC", "task_01DEF"],
audio_indexes: [1, 2],
custom: true,
prompt: "upbeat mashup of the two tracks"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/mashup"
payload := map[string]interface{}{
"model": "suno",
"task_ids": []string{"task_01ABC", "task_01DEF"},
"audio_indexes": []int{1, 2},
"custom": true,
"prompt": "upbeat mashup of the two tracks",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/mashup";
String payload = """
{
"model": "suno",
"task_ids": ["task_01ABC", "task_01DEF"],
"audio_indexes": [1, 2],
"custom": true,
"prompt": "upbeat mashup of the two tracks"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_ids" => ["task_01ABC", "task_01DEF"],
"audio_indexes" => [1, 2],
"custom" => true,
"prompt" => "upbeat mashup of the two tracks"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/mashup")
payload = {
model: "suno",
task_ids: ["task_01ABC", "task_01DEF"],
audio_indexes: [1, 2],
custom: true,
prompt: "upbeat mashup of the two tracks"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/mashup")!
let payload: [String: Any] = [
"model": "suno",
"task_ids": ["task_01ABC", "task_01DEF"],
"audio_indexes": [1, 2],
"custom": true,
"prompt": "upbeat mashup of the two tracks"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/mashup";
var payload = @"{
""model"": ""suno"",
""task_ids"": [""task_01ABC"", ""task_01DEF""],
""audio_indexes"": [1, 2],
""custom"": true,
""prompt"": ""upbeat mashup of the two tracks"""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/mashup";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_ids\":[\"task_01ABC\",\"task_01DEF\"],"
"\"audio_indexes\":[1,2],"
"\"custom\":true,"
"\"prompt\":\"upbeat mashup of the two tracks\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/mashup"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_ids": @[@"task_01ABC", @"task_01DEF"],
@"audio_indexes": @[@1, @2],
@"custom": @YES,
@"prompt": @"upbeat mashup of the two tracks"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/mashup"
let payload = {|{
"model": "suno",
"task_ids": ["task_01ABC", "task_01DEF"],
"audio_indexes": [1, 2],
"custom": true,
"prompt": "upbeat mashup of the two tracks"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/mashup');
final payload = {
'model': 'suno',
'task_ids': ['task_01ABC', 'task_01DEF'],
'audio_indexes': [1, 2],
'custom': true,
'prompt': 'upbeat mashup of the two tracks'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/mashup"
payload <- list(
model = "suno",
task_ids = c("task_01ABC", "task_01DEF"),
audio_indexes = c(1, 2),
custom = TRUE,
prompt = "upbeat mashup of the two tracks"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Array of ythe `task_id`s for the 2 source tracks (must be **exactly 2**; any other count returns `400` directly at submission time).
Array parallel to `task_ids`, selecting which item in each task's result `music[]` (1-based, default `1` for both).
Whether purely instrumental (`true`=no vocals). If omitted, defaults to `false` (with vocals).
Generation version: `v3.5` / `v4` / `v4.5` / `v4.5+` / `v4.5-all` / `v5` / `v5.5`, affects audio quality and billing; defaults to `v5.5` if omitted, and an invalid value returns `400` directly at submission time.
`true`=custom mode (`prompt` used as lyrics); `false`=inspiration mode (uses `gpt_description`); if omitted, inferred from the content (see the Warning above).
Lyrics. Takes effect when `custom=true` (ignored in inspiration mode).
Inspiration prompt. **Required when `custom=false`** — if missing, the request fails with `400` at submission (nothing is charged).
Title. **Only takes effect when `custom=true`**.
Style tags. **Only takes effect when `custom=true`**.
Style tags to exclude. **Only takes effect when `custom=true`**.
`true`=rewrite the provided lyrics creatively. **Only takes effect when `custom=true`**.
Style weight, `0.00`–`1.00` (out-of-range values return `400` directly at submission time). **Only takes effect when `custom=true`**.
Creativity weight, `0.00`–`1.00` (alias `weirdness`). **Only takes effect when `custom=true`**.
Audio weight, `0.00`–`1.00`. **Only takes effect when `custom=true`**.
Vocal gender: `Male` / `Female`. **Works in both modes**.
Persona style id. **Only takes effect when `custom=true`**.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Generate MIDI
Source: https://docs.apimart.ai/en/api-reference/audios/suno/midi
POST https://api.apimart.ai/v1/music/generations/midi
- Generate MIDI from a song.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/midi \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/midi"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/midi";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/midi"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/midi";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/midi")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/midi")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/midi";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/midi";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/midi"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/midi"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/midi');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/midi"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). The result contains the URL of the MIDI output. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Suno Common Conventions & Task Query
Source: https://docs.apimart.ai/en/api-reference/audios/suno/overview
GET https://api.apimart.ai/v1/music/tasks/{task_id}
- Common notes for the Suno music API: authentication, async task lifecycle, model / version, source track references
- Task query: GET /v1/music/tasks/:task_id, poll until completed / failed
This page covers the common conventions shared by all Suno music APIs and is meant to be used alongside the individual documentation for each endpoint. All generation / editing APIs are **asynchronous tasks**: submit to get a `task_id`, then poll the query API on this page to retrieve results.
## Authentication
All requests must include the following in the request headers:
```
Authorization: Bearer
Content-Type: application/json
```
Visit the [API Key management page](https://apimart.ai/keys) to obtain an API Key.
## Task Lifecycle (all APIs are asynchronous)
`POST /v1/music/generations/` → immediately returns the `task_id`:
```json theme={null}
{ "code": 200, "data": [ { "status": "submitted", "task_id": "task_xxx" } ] }
```
`GET /v1/music/tasks/:task_id` until `status` is `completed` or `failed`. While generating, `status` is `pending` and `progress` goes queued `10` → ready `50` → done `100`. A polling interval of 3–5s is recommended; music generation usually takes 30–120s.
On completion, take `audio_url` / `image_url` / `video_url`, etc. from `data.result.music[]`.
Task status transitions: `submitted` → `pending` → `completed` / `failed`. **On failure, `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.**
## Version
`v3.5` / `v4` / `v4.5` / `v4.5+` / `v4.5-all` / `v5` / `v5.5`, affecting audio quality and billing; the default is used if omitted. Availability and defaults vary per endpoint — some support only a subset, and some have no version dimension at all; see each endpoint's own documentation.
## Referencing a Source Track: task\_id + audio\_index
Operations based on an existing song (extend / cover / stem separation / add vocals / trim…) **do not** require you to remember any extra id; you only pass:
* `task_id`: the `task_id` for the task that produced the source track
* `audio_index`: which track in that task's result `music[]` (1-based, defaults to `1`; a single generation usually produces 2 tracks: 1 and 2)
If the source cannot be resolved (task not complete / index out of range / `task_id` not found), a `400` is returned at submission time.
## Query Task: GET /v1/music/tasks/:task\_id
Our `task_id` returned by the submit API.
Poll this API until `status` is `completed` or `failed`. Once completed, retrieve the products from `data.result.music[]`.
## Response
Unique task identifier
Task status: `submitted` / `pending` / `completed` / `failed`
Progress: queued `10` → ready `50` → done `100`
Result data
Present when `status` is `completed`
List of products (a single generation usually produces 2 tracks)
Track id, used with `audio_index` to locate it for subsequent operations
Title
Duration (seconds)
Lyrics
Style tags
Audio file URL
Cover image URL
Large cover image URL
MV video URL (if already generated)
Present when `status` is `failed`
Failure reason (the pre-deducted quota is automatically refunded)
```json completed theme={null}
{
"task_id": "task_01ABC...",
"status": "completed",
"progress": 100,
"data": {
"result": {
"music": [
{
"audio_id": "
# Persona
Source: https://docs.apimart.ai/en/api-reference/audios/suno/persona
POST https://api.apimart.ai/v1/music/generations/persona
- Create a singer Persona from a song; can be bound to the result of "Extract Vox".
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/persona \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"name": "My Persona",
"styles": "pop"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/persona"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"name": "My Persona",
"styles": "pop"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/persona";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
name: "My Persona",
styles: "pop"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/persona"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"name": "My Persona",
"styles": "pop",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/persona";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"name": "My Persona",
"styles": "pop"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"name" => "My Persona",
"styles" => "pop"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/persona")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
name: "My Persona",
styles: "pop"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/persona")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"name": "My Persona",
"styles": "pop"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/persona";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""name"": ""My Persona"",
""styles"": ""pop""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/persona";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"name\":\"My Persona\","
"\"styles\":\"pop\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/persona"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"name": @"My Persona",
@"styles": @"pop"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/persona"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"name": "My Persona",
"styles": "pop"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/persona');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'name': 'My Persona',
'styles': 'pop'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/persona"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
name = "My Persona",
styles = "pop"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Persona name. If missing, returns `400` immediately.
Description.
Style.
The id obtained from "Extract Vox".
Vocal clip start (seconds). When referencing `vox_audio_id`, this must match the clip range used when that Vox was extracted.
Vocal clip end (seconds). When referencing `vox_audio_id`, this must match the clip range used when that Vox was extracted.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). The result contains persona information. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Mastering
Source: https://docs.apimart.ai/en/api-reference/audios/suno/remaster
POST https://api.apimart.ai/v1/music/generations/remaster
- Master an already generated song to improve audio quality, clarity, and overall texture.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/remaster \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/remaster"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/remaster";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
version: "v5"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/remaster"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/remaster";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"version" => "v5"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/remaster")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
version: "v5"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/remaster")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/remaster";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""version"": ""v5""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/remaster";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"version\":\"v5\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/remaster"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"version": @"v5"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/remaster"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"version": "v5"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/remaster');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'version': 'v5'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/remaster"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
version = "v5"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Generation version: **only `v4.5+` / `v5` / `v5.5`**; defaults to `v5.5` if omitted. Any other value (`v3.5` / `v4` / `v4.5` / `v4.5-all`, etc.) returns `400` directly at submission time (with the supported list).
Remaster intensity: `subtle` / `normal` / `high`.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take the mastered `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Remove segment
Source: https://docs.apimart.ai/en/api-reference/audios/suno/remove-section
POST https://api.apimart.ai/v1/music/generations/removeSection
- Remove a time range from a song.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/removeSection \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/removeSection"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/removeSection";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
start_s: 30,
end_s: 45
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/removeSection"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/removeSection";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"start_s" => 30,
"end_s" => 45
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/removeSection")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
start_s: 30,
end_s: 45
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/removeSection")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/removeSection";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""start_s"": 30,
""end_s"": 45
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/removeSection";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"start_s\":30,"
"\"end_s\":45"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/removeSection"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"start_s": @30,
@"end_s": @45
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/removeSection"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/removeSection');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'start_s': 30,
'end_s': 45
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/removeSection"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
start_s = 30,
end_s = 45
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Removal start point (seconds). If missing, returns `400` immediately.
Removal end point (seconds). If missing, returns `400` immediately.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take the processed `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Section replacement
Source: https://docs.apimart.ai/en/api-reference/audios/suno/replace-music
POST https://api.apimart.ai/v1/music/generations/replaceMusic
- Replace a section of a song (infill).
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/replaceMusic \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45,
"infill_lyrics": "A new verse of lyrics"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/replaceMusic"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45,
"infill_lyrics": "A new verse of lyrics"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/replaceMusic";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
start_s: 30,
end_s: 45,
infill_lyrics: "A new verse of lyrics"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/replaceMusic"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45,
"infill_lyrics": "A new verse of lyrics",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/replaceMusic";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45,
"infill_lyrics": "A new verse of lyrics"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"start_s" => 30,
"end_s" => 45,
"infill_lyrics" => "A new verse of lyrics"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/replaceMusic")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
start_s: 30,
end_s: 45,
infill_lyrics: "A new verse of lyrics"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/replaceMusic")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45,
"infill_lyrics": "A new verse of lyrics"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/replaceMusic";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""start_s"": 30,
""end_s"": 45,
""infill_lyrics"": ""A new verse of lyrics""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/replaceMusic";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"start_s\":30,"
"\"end_s\":45,"
"\"infill_lyrics\":\"A new verse of lyrics\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/replaceMusic"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"start_s": @30,
@"end_s": @45,
@"infill_lyrics": @"A new verse of lyrics"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/replaceMusic"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 30,
"end_s": 45,
"infill_lyrics": "A new verse of lyrics"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/replaceMusic');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'start_s': 30,
'end_s': 45,
'infill_lyrics': 'A new verse of lyrics'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/replaceMusic"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
start_s = 30,
end_s = 45,
infill_lyrics = "A new verse of lyrics"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Lyrics for the replacement section.
Replacement start point (seconds). If missing, returns `400` immediately.
Replacement end point (seconds). If missing, returns `400` immediately.
Generation version: `v4` / `v4.5+` / `v5` / `v5.5`; defaults to `v5.5` if omitted. Any other value (including `v3.5` / `v4.5` / `v4.5-all`) returns `400` directly at submission time.
Context lyrics.
Title.
Style tags.
Style tags to exclude.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take the replaced `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Sample to song (sample)
Source: https://docs.apimart.ai/en/api-reference/audios/suno/sample
POST https://api.apimart.ai/v1/music/generations/sample
- Generate a song based on a sample.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
`custom` determines which fields take effect: fields written under the wrong mode are **silently ignored** (no error). With `custom=true`, `prompt` (lyrics), `title`, `tags`, `negative_tags`, `auto_lyrics`, `style_weight`, `weirdness_constraint`, and `audio_weight` take effect and `gpt_description` is ignored; with `custom=false`, only `gpt_description` is read (**required** in that case — if missing, a 400 is returned at submission time). `vocal_gender` works in both modes. If `custom` is omitted, the backend infers it in this order: `prompt` present → `true`; no `prompt` but `gpt_description` present → `false`; otherwise `tags`/`title` present → `true`.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/sample \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 0,
"end_s": 8,
"instrumental": false,
"version": "v5",
"tags": "upbeat pop"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/sample"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 0,
"end_s": 8,
"instrumental": False,
"version": "v5",
"tags": "upbeat pop"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/sample";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
start_s: 0,
end_s: 8,
instrumental: false,
version: "v5",
tags: "upbeat pop"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/sample"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 0,
"end_s": 8,
"instrumental": false,
"version": "v5",
"tags": "upbeat pop",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/sample";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 0,
"end_s": 8,
"instrumental": false,
"version": "v5",
"tags": "upbeat pop"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"start_s" => 0,
"end_s" => 8,
"instrumental" => false,
"version" => "v5",
"tags" => "upbeat pop"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/sample")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
start_s: 0,
end_s: 8,
instrumental: false,
version: "v5",
tags: "upbeat pop"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/sample")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 0,
"end_s": 8,
"instrumental": false,
"version": "v5",
"tags": "upbeat pop"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/sample";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""start_s"": 0,
""end_s"": 8,
""instrumental"": false,
""version"": ""v5"",
""tags"": ""upbeat pop""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/sample";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"start_s\":0,"
"\"end_s\":8,"
"\"instrumental\":false,"
"\"version\":\"v5\","
"\"tags\":\"upbeat pop\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/sample"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"start_s": @0,
@"end_s": @8,
@"instrumental": @NO,
@"version": @"v5",
@"tags": @"upbeat pop"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/sample"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"start_s": 0,
"end_s": 8,
"instrumental": false,
"version": "v5",
"tags": "upbeat pop"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/sample');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'start_s': 0,
'end_s': 8,
'instrumental': false,
'version': 'v5',
'tags': 'upbeat pop'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/sample"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
start_s = 0,
end_s = 8,
instrumental = FALSE,
version = "v5",
tags = "upbeat pop"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track (typically an uploaded sample). If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based: 1 = first track; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Sampling start point (seconds). If missing, returns `400` immediately.
Sampling end point (seconds). If missing, returns `400` immediately.
Whether purely instrumental (`true`=no vocals). If omitted, defaults to `false` (with vocals).
Generation version: `v3.5` / `v4` / `v4.5` / `v4.5+` / `v4.5-all` / `v5` / `v5.5`, affects audio quality and billing; defaults to `v5.5` if omitted, and an invalid value returns `400` directly at submission time.
`true`=custom mode (`prompt` used as lyrics); `false`=inspiration mode (uses `gpt_description`); if omitted, inferred from the content (see the Warning above).
Lyrics. Takes effect when `custom=true` (ignored in inspiration mode).
Inspiration prompt. **Required when `custom=false`** — if missing, the request fails with `400` at submission (nothing is charged).
Title. **Only takes effect when `custom=true`**.
Style tags. **Only takes effect when `custom=true`**.
Style tags to exclude. **Only takes effect when `custom=true`**.
`true`=rewrite the provided lyrics creatively. **Only takes effect when `custom=true`**.
Style weight, `0.00`–`1.00` (out-of-range values return `400` directly at submission time). **Only takes effect when `custom=true`**.
Creativity weight, `0.00`–`1.00` (alias `weirdness`). **Only takes effect when `custom=true`**.
Audio weight, `0.00`–`1.00`. **Only takes effect when `custom=true`**.
Vocal gender: `Male` / `Female`. **Works in both modes**.
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (music generation typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Sound effect generation
Source: https://docs.apimart.ai/en/api-reference/audios/suno/sounds
POST https://api.apimart.ai/v1/music/generations/sounds
- Generate a sound effect from a description.
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/sounds \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"prompt": "A thunderstorm with distant bells"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/sounds"
payload = {
"model": "suno",
"prompt": "A thunderstorm with distant bells"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/sounds";
const payload = {
model: "suno",
prompt: "A thunderstorm with distant bells"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/sounds"
payload := map[string]interface{}{
"model": "suno",
"prompt": "A thunderstorm with distant bells",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/sounds";
String payload = """
{
"model": "suno",
"prompt": "A thunderstorm with distant bells"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"prompt" => "A thunderstorm with distant bells"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/sounds")
payload = {
model: "suno",
prompt: "A thunderstorm with distant bells"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/sounds")!
let payload: [String: Any] = [
"model": "suno",
"prompt": "A thunderstorm with distant bells"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/sounds";
var payload = @"{
""model"": ""suno"",
""prompt"": ""A thunderstorm with distant bells""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/sounds";
const char *payload = "{"
"\"model\":\"suno\","
"\"prompt\":\"A thunderstorm with distant bells\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/sounds"];
NSDictionary *payload = @{
@"model": @"suno",
@"prompt": @"A thunderstorm with distant bells"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/sounds"
let payload = {|{
"model": "suno",
"prompt": "A thunderstorm with distant bells"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/sounds');
final payload = {
'model': 'suno',
'prompt': 'A thunderstorm with distant bells'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/sounds"
payload <- list(
model = "suno",
prompt = "A thunderstorm with distant bells"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Generation version: only `v5` / `v5.5`; defaults to `v5.5` if omitted.
Sound effect text description. If missing, a `400` is returned at submission time (no charge). Prefer English prompts for the best results.
Sound effect type: `one-shot` (default, single hit) / `loop` (loopable).
Tempo, `1`–`300`; out-of-range values return `400` directly at submission time.
Musical key enum: major keys `C` / `C#` / `D` / `D#` / `E` / `F` / `F#` / `G` / `G#` / `A` / `A#` / `B`; minor keys append `m` (`Cm` / `C#m` / … / `Bm`). Only sharp (`#`) notation is supported; flats (`Db` / `Eb`, etc.) and `B#` return `400` (key param error).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion take `audio_url` from `data.result.music[]`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Stem extraction
Source: https://docs.apimart.ai/en/api-reference/audios/suno/stems
POST https://api.apimart.ai/v1/music/generations/stems
- Separate a specified track (e.g. vocals) from a song.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/stems \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"stem_type": "lead_vocal"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/stems"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"stem_type": "lead_vocal"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/stems";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
stem_type: "lead_vocal"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/stems"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"stem_type": "lead_vocal",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/stems";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"stem_type": "lead_vocal"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"stem_type" => "lead_vocal"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/stems")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
stem_type: "lead_vocal"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/stems")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"stem_type": "lead_vocal"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/stems";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""stem_type"": ""lead_vocal""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/stems";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"stem_type\":\"lead_vocal\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/stems"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"stem_type": @"lead_vocal"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/stems"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"stem_type": "lead_vocal"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/stems');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'stem_type': 'lead_vocal'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/stems"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
stem_type = "lead_vocal"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
The stem to extract; defaults to `lead_vocal` (lead vocal). Supports 100+ enum values; common ones: `lead_vocal` / `backing_vocals` / `drum_kit` / `bass` / `piano` / `electric_guitar` / … .
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion the result contains the URL of the separated track. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Full stem separation
Source: https://docs.apimart.ai/en/api-reference/audios/suno/stems-all
POST https://api.apimart.ai/v1/music/generations/stemsAll
- Full multi-track separation.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/stemsAll \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/stemsAll"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/stemsAll";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/stemsAll"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/stemsAll";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/stemsAll")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/stemsAll")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/stemsAll";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/stemsAll";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/stemsAll"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/stemsAll"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/stemsAll');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/stemsAll"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). On completion the result contains the URLs of each stem. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Upload audio
Source: https://docs.apimart.ai/en/api-reference/audios/suno/upload
POST https://api.apimart.ai/v1/music/generations/uploadTask
- Import a piece of public audio to obtain a track that can be referenced later (for cover / continuation, etc.); once complete, this job's `task_id` can serve as the source (`audio_index=1`).
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
**Known limitation**: Do not upload **purely instrumental (vocal-free)** audio — it may fail to parse.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/uploadTask \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"audioFilePath": "https://example.com/my.mp3"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/uploadTask"
payload = {
"model": "suno",
"audioFilePath": "https://example.com/my.mp3"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/uploadTask";
const payload = {
model: "suno",
audioFilePath: "https://example.com/my.mp3"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/uploadTask"
payload := map[string]interface{}{
"model": "suno",
"audioFilePath": "https://example.com/my.mp3",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/uploadTask";
String payload = """
{
"model": "suno",
"audioFilePath": "https://example.com/my.mp3"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"audioFilePath" => "https://example.com/my.mp3"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/uploadTask")
payload = {
model: "suno",
audioFilePath: "https://example.com/my.mp3"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/uploadTask")!
let payload: [String: Any] = [
"model": "suno",
"audioFilePath": "https://example.com/my.mp3"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/uploadTask";
var payload = @"{
""model"": ""suno"",
""audioFilePath"": ""https://example.com/my.mp3""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/uploadTask";
const char *payload = "{"
"\"model\":\"suno\","
"\"audioFilePath\":\"https://example.com/my.mp3\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/uploadTask"];
NSDictionary *payload = @{
@"model": @"suno",
@"audioFilePath": @"https://example.com/my.mp3"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/uploadTask"
let payload = {|{
"model": "suno",
"audioFilePath": "https://example.com/my.mp3"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/uploadTask');
final payload = {
'model': 'suno',
'audioFilePath': 'https://example.com/my.mp3'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/uploadTask"
payload <- list(
model = "suno",
audioFilePath = "https://example.com/my.mp3"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
A publicly accessible direct audio URL. If missing, a `400` is returned at submission time (no charge).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). Once complete, use this job's `task_id` + `audio_index=1` as the source for other operations. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Tag enhancement
Source: https://docs.apimart.ai/en/api-reference/audios/suno/upsample-tags
POST https://api.apimart.ai/v1/music/generations/upsampleTags
- Optimize / expand style tags to improve prompt quality.
- Synchronous endpoint: the result is ready immediately after submitting — no polling wait is required (you may still query `GET /v1/music/tasks/:task_id`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/upsampleTags \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"tags": "pop"
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/upsampleTags"
payload = {
"model": "suno",
"tags": "pop"
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/upsampleTags";
const payload = {
model: "suno",
tags: "pop"
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/upsampleTags"
payload := map[string]interface{}{
"model": "suno",
"tags": "pop",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/upsampleTags";
String payload = """
{
"model": "suno",
"tags": "pop"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"tags" => "pop"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/upsampleTags")
payload = {
model: "suno",
tags: "pop"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/upsampleTags")!
let payload: [String: Any] = [
"model": "suno",
"tags": "pop"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/upsampleTags";
var payload = @"{
""model"": ""suno"",
""tags"": ""pop""
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/upsampleTags";
const char *payload = "{"
"\"model\":\"suno\","
"\"tags\":\"pop\""
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/upsampleTags"];
NSDictionary *payload = @{
@"model": @"suno",
@"tags": @"pop"
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/upsampleTags"
let payload = {|{
"model": "suno",
"tags": "pop"
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/upsampleTags');
final payload = {
'model': 'suno',
'tags': 'pop'
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/upsampleTags"
payload <- list(
model = "suno",
tags = "pop"
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
The style tags to enhance. If missing, a `400` is returned at submission time (no charge).
**Getting the result**: This is a synchronous endpoint — the result is ready immediately after submitting, no polling wait is required (you may still query `GET /v1/music/tasks/{task_id}`, where the completed state is available right away). The optimized tags are returned in the task's text field `result.upsampled_tags`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Extract Vox
Source: https://docs.apimart.ai/en/api-reference/audios/suno/vox
POST https://api.apimart.ai/v1/music/generations/vox
- Extract vocal segments from a song, producing vox reusable by Persona.
- Reference the source track: specified by `task_id` + `audio_index`, no need to record any extra id
- Async task: submitting returns a `task_id`; poll `GET /v1/music/tasks/:task_id` for the result
**Referencing a source track**: Operations based on an existing song require no extra ids—just pass `task_id` (task\_id of the job that produced the source track) + `audio_index` (which track in the result `music[]`, 1-based, defaults to `1`).
This endpoint has **no version dimension**: do not pass `version` — if passed, it is discarded and does not affect billing.
```bash cURL theme={null}
curl -X POST https://api.apimart.ai/v1/music/generations/vox \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"vocal_start_s": 10,
"vocal_end_s": 30
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/music/generations/vox"
payload = {
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"vocal_start_s": 10,
"vocal_end_s": 30
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/music/generations/vox";
const payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
vocal_start_s: 10,
vocal_end_s: 30
};
const headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/music/generations/vox"
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"vocal_start_s": 10,
"vocal_end_s": 30,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer ")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/music/generations/vox";
String payload = """
{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"vocal_start_s": 10,
"vocal_end_s": 30
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"suno",
"task_id" => "task_01ABC",
"audio_index" => 1,
"vocal_start_s" => 10,
"vocal_end_s" => 30
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer ",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/music/generations/vox")
payload = {
model: "suno",
task_id: "task_01ABC",
audio_index: 1,
vocal_start_s: 10,
vocal_end_s: 30
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer "
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/vox")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"vocal_start_s": 10,
"vocal_end_s": 30
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/music/generations/vox";
var payload = @"{
""model"": ""suno"",
""task_id"": ""task_01ABC"",
""audio_index"": 1,
""vocal_start_s"": 10,
""vocal_end_s"": 30
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/music/generations/vox";
const char *payload = "{"
"\"model\":\"suno\","
"\"task_id\":\"task_01ABC\","
"\"audio_index\":1,"
"\"vocal_start_s\":10,"
"\"vocal_end_s\":30"
"}";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/music/generations/vox"];
NSDictionary *payload = @{
@"model": @"suno",
@"task_id": @"task_01ABC",
@"audio_index": @1,
@"vocal_start_s": @10,
@"vocal_end_s": @30
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/music/generations/vox"
let payload = {|{
"model": "suno",
"task_id": "task_01ABC",
"audio_index": 1,
"vocal_start_s": 10,
"vocal_end_s": 30
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/music/generations/vox');
final payload = {
'model': 'suno',
'task_id': 'task_01ABC',
'audio_index': 1,
'vocal_start_s': 10,
'vocal_end_s': 30
};
final response = await http.post(
url,
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
```
```r R theme={null}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/music/generations/vox"
payload <- list(
model = "suno",
task_id = "task_01ABC",
audio_index = 1,
vocal_start_s = 10,
vocal_end_s = 30
)
response <- POST(
url,
add_headers(
Authorization = "Bearer ",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K"
}
]
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden, you do not have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error, please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Gateway error, the server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All endpoints require authentication using a Bearer Token
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to get your API Key
Add the following to the request headers when using it:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Audio model. Currently pass `suno` (defaults to `suno` if omitted).
Our `task_id` of the job that produced the source track. If missing or the source cannot be resolved, a `400` is returned at submission time.
Which track in the source job's result `data.music[]` (1-based; defaults to `1`; a single generation usually produces 2 tracks: indexes 1 and 2).
Start point of the clip (seconds).
End point of the clip (seconds).
**Getting the result**: This endpoint is an async task. After submitting you get a `task_id`; poll `GET /v1/music/tasks/{task_id}` at 3–5s intervals until `status` is `completed` or `failed` (typically takes 30–120s; while generating, `status` is `pending` and `progress` goes queued 10 → ready 50 → done 100). The resulting id can be referenced as Persona's `vox_audio_id`. On failure `data.error.message` gives the reason and the pre-deducted quota is automatically refunded.
## Response
Response status code
Returned data array
Task status
* `submitted` - Submitted
Unique task identifier (used to poll `GET /v1/music/tasks/{task_id}` for the result)
# Download Audio Files
Source: https://docs.apimart.ai/en/api-reference/audios/suno/wav
POST https://api.apimart.ai/v1/music/generations/download
- Download Suno songs as MP3, M4A, or WAV files
- Request multiple formats at once and receive a URL for each file
- Select the source song with task_id and audio_index
- Submit asynchronously and query the music task endpoint for results
The former `POST /v1/music/generations/wav` endpoint is deprecated. It remains temporarily compatible and is equivalent to the new endpoint with `formats: ["wav"]`. New integrations should use `POST /v1/music/generations/download`.
**Select the source song:** pass the `task_id` returned by the task that created the source audio, then use `audio_index` to select a track from its `music[]` result. The index is 1-based and defaults to 1.
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/download \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"]
}'
```
```python Python theme={null}
import requests
response = requests.post(
"https://api.apimart.ai/v1/music/generations/download",
headers={
"Authorization": "Bearer ",
"Content-Type": "application/json",
},
json={
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"],
},
)
print(response.json())
```
```javascript JavaScript theme={null}
const response = await fetch(
"https://api.apimart.ai/v1/music/generations/download",
{
method: "POST",
headers: {
Authorization: "Bearer ",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "suno",
task_id: "task_01JGXXXXXXXXXXXX",
audio_index: 1,
formats: ["mp3", "wav"],
}),
},
);
console.log(await response.json());
```
```json 200 theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JHXXXXXXXXXXXX"
}
]
}
```
```json 400 theme={null}
{
"error": {
"message": "`formats` contains unsupported format `flac`. Supported: mp3 / m4a / wav",
"type": "invalid_request_error",
"code": "invalid_source_reference"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Authentication failed. Check your API key.",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient account balance",
"type": "payment_required"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Too many requests. Try again later.",
"type": "rate_limit_error"
}
}
```
## Authentication
All endpoints require Bearer Token authentication. Get your key from the [API Key page](https://apimart.ai/keys).
```
Authorization: Bearer YOUR_API_KEY
```
## Request parameters
Model name. Use `suno`; omitted values default to `suno`.
The task ID returned when the source song was created.
The source task must belong to the current account, be completed, and contain a downloadable audio track. Music generation, extension, cover, and stem tasks can be used; text-only tasks such as lyrics or BPM analysis cannot.
The track to download from the source task's `music[]` result.
* 1-based index
* Default: `1`
* Must not exceed the number of tracks in the source task
Array of requested file formats. At least one item is required.
Supported values:
* `mp3`
* `m4a`
* `wav`
Multiple formats may be requested together. Values are case-insensitive and duplicates are removed automatically. Result order matches request order.
For a single format, this field can be used instead of `formats`.
Example: `"format": "mp3"`
Use either `formats` or `format`. Omitting both, or passing an empty format list, returns HTTP 400.
## Submission response
Successful submission returns a new download-task `task_id`:
```json theme={null}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JHXXXXXXXXXXXX"
}
]
}
```
`data` is an array; read `data[0].task_id`. This is the new download task ID, not the source-song `task_id` sent in the request.
## Query download results
Query with the download task ID from the submission response:
```http theme={null}
GET /v1/music/tasks/{task_id}
```
Files are usually prepared during submission, so query once immediately. If the status is neither `completed` nor `failed`, poll every 2 seconds for up to 60 seconds.
### Completed
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01JHXXXXXXXXXXXX",
"status": "completed",
"progress": 100,
"created": 1756800000,
"completed": 1756800003,
"actual_time": 3,
"cost": 0.01,
"credits_cost": 0.1,
"result": {
"music_id": "518c74ee-62ac-4ccd-b3d9-7003acd12ad7",
"files": [
{
"format": "mp3",
"url": "https://assets.apimart.ai/audio/example.mp3"
},
{
"format": "wav",
"url": "https://assets.apimart.ai/audio/example.wav"
}
],
"wavUrl": "https://assets.apimart.ai/audio/example.wav"
}
}
}
```
Read `result.files[]` to obtain downloads:
| Field | Type | Description |
| -------- | ------ | --------------------- |
| `format` | string | `mp3` / `m4a` / `wav` |
| `url` | string | File download URL |
`result.wavUrl` only exists for compatibility with the legacy WAV endpoint. New code should always read `result.files[]`.
### Processing
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01JHXXXXXXXXXXXX",
"status": "processing",
"progress": 50,
"created": 1756800000
}
}
```
There is no `result` yet. Continue polling.
### Failed
```json theme={null}
{
"code": 200,
"data": {
"id": "task_01JHXXXXXXXXXXXX",
"status": "failed",
"progress": 100,
"cost": 0,
"error": {
"message": "Upstream request failed"
}
}
}
```
Failed tasks are refunded automatically and return `cost: 0`. Display `error.message` and offer a retry.
## File URLs
Results normally use APIMart's file domain. If storage transfer fails, an upstream CDN URL may be returned and its lifetime is not guaranteed.
Download and store the file promptly. Do not rely on a temporary URL for long-term storage.
## Errors
Submission validation errors return HTTP 400 before task creation and billing:
| Error text | Cause |
| --------------------------------------------------- | ------------------------------------------------------------ |
| `formats is required` / `must contain at least one` | Missing format |
| `unsupported format` | Value other than `mp3` / `m4a` / `wav` |
| `task_id is required` / `invalid task_id format` | Missing or malformed source task ID |
| `source task not found` | Source task does not exist or belongs to another account |
| `audio_index N out of range` | Track index exceeds the source result |
| `track #N has no music_id` | Source task is unfinished or the selected track has no audio |
HTTP 403 with `model_price_not_configured` means `suno@download` pricing is not configured; contact platform support.
## Billing and repeated downloads
The download endpoint is billed per request:
* One request with multiple formats incurs one charge
* Submitting the same song again creates another charge, even for the same format
* Requesting another format in a later task incurs another charge
* Failed download tasks are refunded automatically
Reuse returned file URLs and disable the download button while a request is in progress to prevent duplicate submissions and charges.
## Migrate from the legacy endpoint
| Item | Legacy | Current |
| ------------- | --------------------------- | ----------------------------------------------------- |
| Request path | `/v1/music/generations/wav` | `/v1/music/generations/download` |
| Formats | WAV only | MP3 / M4A / WAV; multiple allowed |
| New parameter | — | `formats` or `format` |
| Result | `result.wavUrl` | `result.files[]` |
| Compatibility | `result.wavUrl` | May also return `result.wavUrl` when WAV is requested |
The legacy endpoint remains temporarily available, but all new code should use `/generations/download`.
## Response
Response status code; 200 on success
Submission response data
Initially `submitted`
Download task ID used to poll `GET /v1/music/tasks/{task_id}`
# omni-moderation-latest Content Moderation
Source: https://docs.apimart.ai/en/api-reference/moderations/omni-moderation-latest/generation
POST https://api.apimart.ai/v1/moderations
- Supports text, image, and mixed text+image content moderation
- Compatible with single text, text array, and content block array inputs
- Images support public URLs and base64 Data URIs
Use `omni-moderation-latest` to perform safety moderation on input content. This model belongs to the Moderation Series and is not part of the image, video, or audio generation series.
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/moderations \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"model": "omni-moderation-latest",
"input": [
{
"type": "text",
"text": "Please moderate whether this image is compliant"
},
{
"type": "image_url",
"image_url": {
"url": "https://cdn.apimart.ai/files/1779955589195-wh950j4imqd.jpeg"
}
}
],
"stream": false
}'
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/moderations"
payload = {
"model": "omni-moderation-latest",
"input": [
{
"type": "text",
"text": "Please moderate whether this image is compliant"
},
{
"type": "image_url",
"image_url": {
"url": "https://cdn.apimart.ai/files/1779955589195-wh950j4imqd.jpeg"
}
}
],
"stream": False
}
headers = {
"Authorization": "Bearer ",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/moderations";
const payload = {
model: "omni-moderation-latest",
input: [
{
type: "text",
text: "Please moderate whether this image is compliant",
},
{
type: "image_url",
image_url: {
url: "https://cdn.apimart.ai/files/1779955589195-wh950j4imqd.jpeg",
},
},
],
stream: false,
};
const headers = {
Authorization: "Bearer ",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
```
## Supported Models
| Model | Description | Supported Inputs |
| ------------------------ | ---------------------------------------- | ----------------------------- |
| `omni-moderation-latest` | General-purpose content moderation model | Text, image, mixed text+image |
## Authorizations
All endpoints require authentication using a Bearer Token.
Get an API Key:
Visit the [API Key management page](https://apimart.ai/keys) to obtain your API Key.
Add the following header in your request:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Moderation model name.
* `omni-moderation-latest` - General-purpose content moderation model
Content to be moderated. Supports plain text, text array, or content block array.
Content blocks can include:
* `text` - Text content block
* `image_url` - Image URL content block
Whether to stream the response.
* `false`: Non-streaming response (default; the only value currently supported, `true` is not supported)
## input Request Modes
### Mixed Text + Image
```json theme={null}
{
"model": "omni-moderation-latest",
"input": [
{
"type": "text",
"text": "Please moderate whether this image is compliant"
},
{
"type": "image_url",
"image_url": {
"url": "https://cdn.apimart.ai/files/1779955589195-wh950j4imqd.jpeg"
}
}
],
"stream": false
}
```
### Plain Text (Single)
```json theme={null}
{
"model": "omni-moderation-latest",
"input": "I want to kill someone",
"stream": false
}
```
### Plain Text (Array)
```json theme={null}
{
"model": "omni-moderation-latest",
"input": [
"hello",
"I hate you"
],
"stream": false
}
```
### Image Only (Image URL)
```json theme={null}
{
"model": "omni-moderation-latest",
"input": [
{
"type": "image_url",
"image_url": {
"url": "https://cdn.apimart.ai/files/1779955589195-wh950j4imqd.jpeg"
}
}
],
"stream": false
}
```
### Image Only (base64 Data URI)
```json theme={null}
{
"model": "omni-moderation-latest",
"input": [
{
"type": "image_url",
"image_url": {
"url": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAA..."
}
}
],
"stream": false
}
```
## Notes
1. When `input` is a content block array, each element uses `type` to distinguish content type.
2. For image moderation, prefer using publicly accessible URLs. If using base64, follow the standard Data URI format: `data:image/{format};base64,{data}`.
3. Unless required otherwise, set `stream: false` consistently.
# Get Task Status
Source: https://docs.apimart.ai/en/api-reference/tasks/status
GET https://api.apimart.ai/v1/tasks/{task_id}
- Query the execution status and result of an asynchronous task
- Real-time status updates and progress tracking
- Retrieve generation results when tasks are completed
- Error messages available in 10 languages (en/zh/ja/ko/ru/fr/de/id/pt/es)
```bash cURL theme={null}
curl --request GET \
--url https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en \
--header 'Authorization: Bearer '
```
```python Python theme={null}
import requests
url = "https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt"
headers = {
"Authorization": "Bearer "
}
params = {
"language": "en"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())
```
```javascript JavaScript theme={null}
const url = "https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en";
const headers = {
"Authorization": "Bearer "
};
fetch(url, {
method: "GET",
headers: headers
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```go Go theme={null}
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer ")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={null}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer ")
.GET()
.build();
HttpResponse response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```php PHP theme={null}
"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
```
```ruby Ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = "Bearer "
response = http.request(request)
puts response.body
```
```swift Swift theme={null}
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("Bearer ", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
```
```csharp C# theme={null}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer ");
var response = await client.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
```
```c C theme={null}
#include
#include
int main(void) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer ");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
```
```objectivec Objective-C theme={null}
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"GET"];
[request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
```
```ocaml OCaml theme={null}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en"
let () =
let headers = Header.init ()
|> fun h -> Header.add h "Authorization" "Bearer "
in
let response = Client.get ~headers (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
```
```dart Dart theme={null}
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer ',
},
);
print(response.body);
}
```
```r R theme={null}
library(httr)
url <- "https://api.apimart.ai/v1/tasks/task-unified-1757156493-imcg5zqt?language=en"
response <- GET(
url,
add_headers(
Authorization = "Bearer "
)
)
cat(content(response, "text"))
```
```json 200 - Image Generation Task theme={null}
{
"code": 200,
"data": {
"id": "task_01KA040M0HP1GJWBJYZMKX1XS1",
"status": "completed",
"cost": 0.15,
"credits_cost": 1.5,
"progress": 100,
"result": {
"images": [
{
"url": [
"https://upload.apimart.ai/f/image/9998236911693428-e8d7441f-f7b4-4130-97ad-9ef8a0dde2ce-image_task_01KA0413RT2GGNZJ9GWQ4PXF2F_0.png"
],
"expires_at": 1763174708
}
]
},
"created": 1763088289,
"completed": 1763088308,
"estimated_time": 60,
"actual_time": 19
}
}
```
```json 400 theme={null}
{
"error": {
"code": 400,
"message": "Invalid task ID",
"type": "invalid_request_error"
}
}
```
```json 401 theme={null}
{
"error": {
"code": 401,
"message": "Invalid authentication credentials",
"type": "authentication_error"
}
}
```
```json 402 theme={null}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up your account",
"type": "payment_required"
}
}
```
```json 403 theme={null}
{
"error": {
"code": 403,
"message": "Access forbidden. You don't have permission to access this resource",
"type": "permission_error"
}
}
```
```json 429 theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 theme={null}
{
"error": {
"code": 500,
"message": "Internal server error. Please try again later",
"type": "server_error"
}
}
```
```json 502 theme={null}
{
"error": {
"code": 502,
"message": "Bad gateway. The server is temporarily unavailable",
"type": "bad_gateway"
}
}
```
## Authorizations
All API endpoints require Bearer Token authentication
Get your API Key:
Visit the [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add it to the request header:
```
Authorization: Bearer YOUR_API_KEY
```
## Path parameters
Task ID returned by the generation API
## Query parameters
Language of `error.message` for failed tasks. Supported values:
* `en` - English
* `zh` - Simplified Chinese
* `ja` - Japanese
* `ko` - Korean
* `ru` - Russian
* `fr` - French
* `de` - German
* `id` - Indonesian
* `pt` - Portuguese
* `es` - Spanish
Values are case-insensitive, and surrounding whitespace is trimmed. Use the two-letter codes above; regional tags such as `zh-CN`, `en-US`, and `pt-BR` are not recognized.
This parameter only affects `error.message`. If omitted or set to an unsupported value, the original error message is returned.
## Response
Unique task identifier
Task status values:
* `pending` - Queued for processing
* `processing` - In progress
* `completed` - Finished successfully
* `failed` - Failed
* `cancelled` - Cancelled by user
Cost charged for this task
Credits charged for this task
Task progress percentage (0–100)
Task result, returned only when status is `completed`
Array of generated image objects (for image generation tasks)
Array of generated video objects (for video generation tasks)
Task creation timestamp
Task completion timestamp (only present when completed)
Estimated completion time in seconds
Actual completion time in seconds (only present when completed)
Error details (only present when status is `failed`)
Error code
Error message
Error type
# Task Completion Callback (Webhook)
Source: https://docs.apimart.ai/en/api-reference/tasks/webhook
Include a callback URL when submitting an async generation task, and we'll POST the result once it finishes, with an optional language for failure messages.
When submitting async generation tasks such as video / image / audio, you can include a callback URL. **Once the task finishes (succeeds or fails)**, we'll actively POST the result to your URL, so you don't have to keep polling. For video and image generation tasks, you can also use `language` to choose the language of failure messages.
## Quick start
When submitting a task, add `webhook` at the top level of the request body. To translate failure messages, also add `language`:
```bash theme={null}
curl -X POST https://your-access-domain/v1/images/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "a red apple on a table",
"size": "1024x1024",
"webhook": "https://your-server.com",
"language": "en"
}'
```
After the task is done, we'll send a POST request to **`your URL + /callback`**.
Other async task endpoints (video, audio, etc.) use `webhook` in the same way. `language` currently applies to `POST /v1/videos/generations` and `POST /v1/images/generations`; both fields belong at the top level of the request body.
## Choose the error message language
`language` is an optional string parameter that only affects `error.message` in failure callbacks. Task IDs, status, progress, cost, and result URLs do not change with the language. If omitted, the original error message from the upstream provider or platform is returned.
| Language | Value | Language | Value |
| ------------------ | ----- | ---------- | ----- |
| English | `en` | Russian | `ru` |
| Simplified Chinese | `zh` | French | `fr` |
| Japanese | `ja` | German | `de` |
| Korean | `ko` | Indonesian | `id` |
| Portuguese | `pt` | Spanish | `es` |
* Values are case-insensitive, and surrounding whitespace is trimmed. For example, `"EN"` and `" en "` are both treated as `en`.
* Use the two-letter codes in the table. Regional tags such as `zh-CN`, `en-US`, and `pt-BR` are not recognized.
* Unsupported values do not cause task submission to fail; the callback keeps the original error message.
* If the original message is already in the target language, it is returned unchanged instead of being translated again.
* If translation fails, the original message is returned without delaying or dropping the callback.
When polling, use the [`language` query parameter on the task status endpoint](/en/api-reference/tasks/status#query-parameters) to choose the same error message language. A webhook has no query string, so `language` must be specified **when submitting the task**.
`POST /mj/submit/*` and `POST /v1/images/edits` do not support `webhook` / `language`. Official xAI image models do not support `language` and return `400 parameter "language" is not supported` when it is included. Do not send this parameter to those models.
## URL rules
The `webhook` you provide is the **base URL**, and we automatically append `/callback`:
| Your `webhook` | Where we actually POST |
| ------------------------------ | -------------------------------------- |
| `https://your-server.com` | `https://your-server.com/callback` |
| `https://your-server.com/api` | `https://your-server.com/api/callback` |
| `https://your-server.com/api/` | `https://your-server.com/api/callback` |
So your server needs an endpoint that accepts `POST .../callback`.
## What you'll receive
The pushed payload is **exactly the same as what the "[Get Task Status](/en/api-reference/tasks/status)" endpoint returns** — you can process it with the same parsing logic.
```json Success (status: completed) theme={null}
{
"id": "task_01KV7FXR8BEYS1BWHJCT3JMCJ5",
"status": "completed",
"progress": 100,
"created": 1781589029,
"completed": 1781589058,
"actual_time": 29,
"cost": 0.006,
"credits_cost": 0.06,
"result": {
"images": [{ "url": ["https://.../result.png"], "expires_at": 1781675458 }]
}
}
```
```json Failure (status: failed) theme={null}
{
"id": "task_xxx",
"status": "failed",
"progress": 100,
"created": 1781589029,
"completed": 1781589050,
"error": {
"message": "The input image cannot be accessed. Make sure the URL is publicly accessible.",
"type": "task_failed",
"param": "",
"code": "task_failed"
}
}
```
For video tasks the result is in `result.videos`, and for audio in `result.audios`.
The failure example above uses `"language": "en"`. The language parameter only changes `error.message`; all other fields remain the same.
We only push when a task reaches a **terminal state** (`completed` / `failed`); we don't push while processing.
## Retries and deduplication (important)
* **Retries**: If your server doesn't return `2xx` within about 10 seconds, or returns `5xx`, we'll retry automatically, up to **3 times**, at intervals of roughly **10s, 30s, and 60s**. If all 3 fail we give up (within about 2 minutes).
* **No retry**: If your endpoint returns `4xx` (treated as a bad URL / request), we give up immediately without retrying.
* **Deduplication**: Normally a task is pushed only once. But in extreme cases (e.g. a restart on our side after sending but before confirmation) you **may receive duplicate pushes**. Be sure to **deduplicate idempotently by `id` (task\_id)** to avoid double-processing.
**Recommendations for your receiving endpoint:**
Accept and enqueue first, then process asynchronously — don't make us wait for your processing to finish.
Use `id` (task\_id) as the idempotency key to avoid double-processing.
In production, verify the origin of callback requests and reject forged ones.
## Requirements for the callback URL
For security, the callback URL must meet the following:
| Requirement | Description |
| ------------------- | -------------------------------------------------------------------------------------------------- |
| Publicly accessible | **Cannot** be an internal / local address (e.g. `127.0.0.1`, `10.x`, `192.168.x` will be rejected) |
| Protocol | `http` or `https` (`https` recommended) |
| Port | Use standard ports (`80` / `443`); non-standard ports may be blocked |
| Domain | Cannot point to our own service domain |
URLs that don't meet these requirements are dropped (no push, no retry).
## FAQ
Check the following one by one:
1. Did the task **actually finish**? Check the task details — is `status` `completed` / `failed` (no push while processing)?
2. Is your URL **publicly accessible**? Can we reach your `/callback`?
3. Is the port a standard port (80 / 443)? Non-standard ports may be blocked by security policies.
4. Did your `/callback` **return 2xx promptly**? Returning 4xx is given up immediately.
5. Are you using `https`? Is the certificate valid?
Some models produce multiple images at once, so `images[].url` may be an array — just handle it as an array.
If `result` includes `expires_at` (a Unix timestamp), it indicates the link's expiration time — transfer/store it promptly.
No. We only push once, when the task finally succeeds or fails.
## Minimal receiver example
```python Python theme={null}
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
class H(BaseHTTPRequestHandler):
def do_POST(self):
n = int(self.headers.get("Content-Length") or 0)
body = self.rfile.read(n)
data = json.loads(body)
print("Received task callback:", data["id"], data["status"])
# TODO: deduplicate by id, verify the signature, then process
self.send_response(200); self.end_headers()
self.wfile.write(b'{"ok":true}')
HTTPServer(("0.0.0.0", 443), H).serve_forever()
```
Return `200` as soon as possible, and run your processing logic asynchronously in the background.
# Upload Image
Source: https://docs.apimart.ai/en/api-reference/uploads/images
POST https://api.apimart.ai/v1/uploads/images
Upload an image to get a URL for use with image/video generation APIs
**The doc Playground does not support file uploads**: Please use the cURL, Python, or JavaScript code examples below to test.
**Temporary storage:** Uploaded images are stored for only **72 hours**. After that, the image URL will expire. Use the image within this period or save it to your own storage service in time.
**Important Change:** For better performance and cost control, we no longer support passing base64 image data directly in generation APIs. Please use this API to upload images, get the URL, and then call the generation API.
## Why upload images first?
1. **Performance Optimization** - base64 encoding inflates data by 33%, uploading first significantly reduces request body size
2. **Reuse Images** - Upload once, reuse the URL multiple times without redundant transfers
## Workflow
```mermaid theme={null}
sequenceDiagram
participant Client
participant APIMart
participant Storage
Client->>APIMart: POST /v1/uploads/images (Upload image file)
APIMart->>Storage: Save image
Storage-->>APIMart: Return storage path
APIMart-->>Client: Return image URL
Client->>APIMart: POST /v1/images/generations (Use image URL)
```
```bash cURL theme={null}
curl --request POST \
--url https://api.apimart.ai/v1/uploads/images \
--header 'Authorization: Bearer ' \
--form 'file=@/path/to/your/image.jpg'
```
```python Python theme={null}
import requests
# Upload image
with open('image.jpg', 'rb') as f:
response = requests.post(
"https://api.apimart.ai/v1/uploads/images",
headers={
"Authorization": "Bearer "
},
files={
"file": f
}
)
result = response.json()
image_url = result['url']
print(f"Image URL: {image_url}")
# Use the uploaded image for generation
response = requests.post(
"https://api.apimart.ai/v1/images/generations",
headers={
"Authorization": "Bearer ",
"Content-Type": "application/json"
},
json={
"model": "gemini-3-pro-image-preview",
"prompt": "Create a variation based on this image",
"image_urls": [{"url": image_url}]
}
)
```
```javascript JavaScript theme={null}
// Upload image
const formData = new FormData();
formData.append('file', fileInput.files[0]);
const uploadResponse = await fetch('https://api.apimart.ai/v1/uploads/images', {
method: 'POST',
headers: {
'Authorization': 'Bearer '
},
body: formData
});
const uploadResult = await uploadResponse.json();
const imageUrl = uploadResult.url;
console.log(`Image URL: ${imageUrl}`);
// Use the uploaded image for generation
const genResponse = await fetch('https://api.apimart.ai/v1/images/generations', {
method: 'POST',
headers: {
'Authorization': 'Bearer ',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gemini-3-pro-image-preview',
prompt: 'Create a variation based on this image',
image_urls: [{url: imageUrl}]
})
});
```
```json 200 theme={null}
{
"url": "https://upload.apimart.ai/f/image/9990000123456-a1b2c3d4-photo.jpg",
"filename": "photo.jpg",
"content_type": "image/jpeg",
"bytes": 235680,
"created_at": 1743436800
}
```
```json 400 - Missing File Field theme={null}
{
"error": {
"message": "missing or invalid file field: http: no such file",
"type": "invalid_request_error"
}
}
```
```json 400 - Unsupported Format theme={null}
{
"error": {
"message": "unsupported image type: application/pdf, allowed: jpeg, png, gif, webp",
"type": "invalid_request_error"
}
}
```
```json 413 - File Too Large theme={null}
{
"error": {
"message": "file size 25165824 exceeds maximum 20971520 bytes",
"type": "invalid_request_error"
}
}
```
```json 429 - Rate Limit Exceeded theme={null}
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please try again later",
"type": "rate_limit_error"
}
}
```
```json 500 - Upload Failed theme={null}
{
"error": {
"message": "failed to upload image",
"type": "server_error"
}
}
```
## Authorizations
All APIs require Bearer Token authentication
Get API Key:
Visit [API Key Management Page](https://apimart.ai/keys) to get your API Key
Add to request headers:
```
Authorization: Bearer YOUR_API_KEY
```
## Body
Image file
Supported formats: JPEG (.jpg, .jpeg), PNG (.png), WebP (.webp), GIF (.gif)
Maximum file size: 20MB
## Response
Public access URL for the image, can be used directly in generation APIs (valid for 72 hours)
Original file name
Detected MIME type, e.g. `image/jpeg`
File size in bytes
Upload time as Unix timestamp (seconds)
## Full Example: Image-to-Image Workflow
```python Python theme={null}
import requests
import time
API_KEY = "your-Apimart-key"
BASE_URL = "https://api.apimart.ai"
# Step 1: Upload reference image
def upload_image(file_path):
with open(file_path, 'rb') as f:
response = requests.post(
f"{BASE_URL}/v1/uploads/images",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": f}
)
return response.json()['url']
# Step 2: Create generation task
def create_generation(image_url, prompt):
response = requests.post(
f"{BASE_URL}/v1/images/generations",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"model": "gemini-3-pro-image-preview",
"prompt": prompt,
"image_urls": [{"url": image_url}],
"size": "16:9"
}
)
return response.json()['id']
# Step 3: Poll task status
def wait_for_result(task_id):
while True:
response = requests.get(
f"{BASE_URL}/v1/images/generations/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"}
)
result = response.json()
if result['status'] == 'completed':
return result['url']
elif result['status'] == 'failed':
raise Exception(f"Generation failed: {result.get('fail_reason')}")
time.sleep(2)
# Execute workflow
image_url = upload_image("reference.jpg")
print(f"Image uploaded: {image_url}")
task_id = create_generation(image_url, "Transform this photo into Ghibli anime style")
print(f"Task created: {task_id}")
result_url = wait_for_result(task_id)
print(f"Generation complete: {result_url}")
```
# Development Guide
Source: https://docs.apimart.ai/en/development
Integrate the API into your application
# Development Guide
This guide helps you integrate our API services into your application.
## Asynchronous Processing
Our API uses an asynchronous processing model:
1. Submit a task: send a generation request and receive a task ID
2. Poll status: periodically check task status
3. Get results: fetch generation results when the task completes
### Polling example
```python theme={null}
import time
import requests
def wait_for_completion(api_key, task_id, max_wait=300):
"""Poll the task until it completes"""
url = f"https://api.apimart.ai/v1/tasks/{task_id}"
headers = {"Authorization": f"Bearer {api_key}"}
start_time = time.time()
while time.time() - start_time < max_wait:
data = requests.get(url, headers=headers).json()["data"]
status = data["status"]
if status == "completed":
return data["result"]
elif status in ("failed", "cancelled"):
raise Exception(f"Task {status}: {data.get('error')}")
time.sleep(2) # wait 2 seconds before polling again
raise Exception("Task timeout")
```
## Error Handling
### Common errors
| Status | Description | Resolution |
| ------ | -------------------------- | ----------------------------------- |
| 400 | Invalid request parameters | Check request parameters and format |
| 401 | Authentication failed | Verify your API key |
| 402 | Insufficient balance | Top up your account balance |
| 429 | Rate limit exceeded | Reduce request frequency |
| 500 | Server error | Retry later |
### Example
```python theme={null}
import requests
response = requests.post(
"https://api.apimart.ai/v1/images/generations",
headers={"Authorization": f"Bearer {api_key}"},
json={"model": "gpt-4o-image", "prompt": "a cute panda"},
)
if response.status_code != 200:
error = response.json().get("error", {})
if response.status_code == 401:
print("Invalid API key")
elif response.status_code == 402:
print("Insufficient account balance")
else:
print(f"Error: {error.get('message')}")
```
## Best Practices
1. Caching: generated image/video links are valid for 24 hours
2. Retries: implement exponential backoff on transient errors
3. Monitoring: regularly check API usage and quotas
4. Security: keep your API key secure
## Support
If you run into issues during development, you can get help via:
* Email: [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
* Live chat: visit our website
* Docs: browse the full API documentation
# FAQs
Source: https://docs.apimart.ai/en/faqs
Frequently Asked Questions about using APIMart
Welcome to the APIMart FAQ page! Here you'll find answers to the most common questions users encounter.
## Question Categories
Troubleshoot connection failures, response errors and usage issues
View usage, costs and get technical support
API key management and security best practices
Learn about supported models and API compatibility
Practical tips for optimizing API call costs
## Quick Links
View complete API interface documentation
Get started with APIMart services quickly
Learn how to integrate APIMart
Access APIMart management console
View detailed pricing for all models
## Need More Help?
If you didn't find your answer above, feel free to contact us:
* Join our [Discord community](https://discord.gg/V8zqssyZ5c)
* Follow [Twitter @APIMart\_](https://x.com/APIMart_)
* Add WeChat customer service (scan QR code in dashboard)
# Account Management
Source: https://docs.apimart.ai/en/faqs/account-management
Account usage and technical support inquiries
## Q4: How to view API usage and costs?
You can view usage and costs by:
1. Logging into [APIMart Dashboard](https://apimart.ai)
2. Viewing usage statistics in the console
3. Checking detailed call records and billing details
## Q5: How to get technical support?
If you need technical support, you can contact us through:
* Join our [Discord community](https://discord.gg/V8zqssyZ5c)
* Follow us on [Twitter @APIMart\_](https://x.com/APIMart_)
* Add WeChat customer service (scan QR code in dashboard)
* Send email to our technical support team
# Connection & Usage
Source: https://docs.apimart.ai/en/faqs/connection-usage
Troubleshoot connection and usage issues with APIMart
## Q1: Unable to connect to APIMart service?
If you cannot connect to APIMart service, please check the following:
* Verify your API Key is correctly configured
* Check your network connection
* Confirm the API endpoint address is correct: `https://api.apimart.ai`
* Check if firewall or proxy settings are blocking the connection
## Q2: No response or errors after selecting a model?
This could be due to:
* API Key not properly configured or expired
* Selected model may be temporarily unavailable
* Incorrect request format
* Insufficient account balance
Please visit the [APIMart Dashboard](https://apimart.ai) to check your account status and API key.
## Q3: What to do when encountering dialogue errors or interruptions?
When encountering dialogue errors:
* Check the specific information in the error message
* Verify request parameters comply with API specifications
* Review API documentation for correct request format
* Contact technical support if the issue persists
# Cost Optimization
Source: https://docs.apimart.ai/en/faqs/cost-optimization
Practical tips for optimizing API call costs
## Q9: How to optimize API call costs?
Suggestions for cost optimization:
* Choose models suitable for your needs (different models have different prices)
* Use streaming responses to reduce waiting time
* Set reasonable token limits
* Cache common responses
* Monitor usage to avoid unexpected consumption
**Practical Tips**
1. **Choose the right model**: For simple tasks, lower-cost models can achieve good results
2. **Set max\_tokens**: Limiting response length can effectively control costs
3. **Implement caching strategy**: Caching results for repeated or similar requests can significantly reduce call counts
4. **Use streaming responses**: Improves user experience while allowing early problem detection and unnecessary request interruption
Learn about detailed pricing for each model
# Features & Capabilities
Source: https://docs.apimart.ai/en/faqs/features
APIMart supported features and compatibility information
## What AI models are supported?
APIMart supports various mainstream AI models, including:
* **Text Models**: GPT-5, Claude, Gemini, etc.
* **Image Models**: GPT-4o-image, Gemini-2.5-Flash-Image-preview, etc.
* **Video Models**: Sora2, VEO3, etc.
* **Audio Models**: Whisper-1, TTS, etc.
Please check the [API Documentation](/en/index) for specific supported models.
## How compatible is it with OpenAI API?
APIMart is fully compatible with OpenAI API format, allowing you to:
* Directly replace the API endpoint
* Use the same request format
* No need to modify existing code
* Support all major OpenAI API features
Simply replace the original OpenAI API endpoint `https://api.openai.com` with `https://api.apimart.ai` for seamless migration.
## Why do API responses differ from official web versions (like ChatGPT, Claude)?
While using the same underlying models, there are differences between official web versions and API calls:
**Official Web Versions** include extensive engineering optimizations and enhanced features:
* Built-in internet search for real-time information
* Conversation memory that automatically links context
* Built-in calculator and code execution environment
* Pre-configured system prompts
* Optimized user interface
**API Calls** provide raw model capabilities:
* Only core reasoning and generation abilities
* Developers must manually manage conversation history
* Requires manual configuration of system prompts and context
* Requires self-integration of tool calling (Function Calling)
**Development Tip**: When using the API, actively configure system prompts (system messages), maintain conversation history, and integrate tool calling features as needed to achieve an experience closer to the web version.
# Security & Configuration
Source: https://docs.apimart.ai/en/faqs/security-configuration
API key management and security configuration guide
## Q6: How to manage and protect API Keys?
Protect your API Key security:
* Do not commit API Keys in public code repositories
* Use environment variables to store API Keys
* Rotate API Keys regularly
* If an API Key is leaked, regenerate it immediately in the dashboard
API Key leaks can lead to unauthorized usage and financial losses. Please keep them secure.
We recommend using different API Keys for different environments (development, testing, production) for better management and security isolation.
# Using APIMart in AnythingLLM
Source: https://docs.apimart.ai/en/integrations/chat/anythingllm
Detailed guide on how to configure and use APIMart API service in AnythingLLM. This guide will help you configure APIMart API in AnythingLLM to build private AI knowledge bases and conversation systems.
## Prerequisites
Before you begin, please ensure:
1. **AnythingLLM installed**\
Download and install AnythingLLM from [official website](https://anythingllm.com/) or visit [GitHub](https://github.com/Mintplex-Labs/anything-llm)
2. **APIMart API Key obtained**\
Log in to [APIMart Console](https://apimart.ai/keys) to get your API key (starts with `sk-`)
**Tip:** If you don't have an APIMart account yet, please register at [APIMart](https://apimart.ai) and obtain an API key first.
## Step 1: Launch AnythingLLM and Access Settings
### 1.1 Start the Application
1. Launch AnythingLLM desktop application or access the web version
2. Welcome screen will appear on first launch
3. Click the **Open settings** button in the bottom left corner
*AnythingLLM main interface showing workspace list and settings access*
**Note:** AnythingLLM supports desktop versions (Windows, macOS, Linux) and Docker deployment.
### 1.2 Navigate to LLM Configuration
In the settings page:
1. Find **LLM Preference** in the left menu
2. Click to enter LLM configuration page
## Step 2: Configure APIMart API
### 2.1 Select LLM Provider
On the LLM configuration page:
1. Find the **LLM Provider** dropdown menu
2. Select **Generic OpenAI**
*Select Generic OpenAI as the LLM provider*
**Why Generic OpenAI?** APIMart provides OpenAI-compatible API interface, so selecting Generic OpenAI provider in AnythingLLM allows you to use APIMart services.
### 2.2 Configure API Information
After selecting Generic OpenAI, fill in the following configuration:
| Field | Value |
| --------------------------------- | -------------------------------------------------------- |
| **API Key** | Your APIMart API key (`sk-xxxxxxxxxxxx`) |
| **Base URL** or **API Base Path** | `https://api.apimart.ai/v1` |
| **Chat Model** or **Model Name** | Enter specific model name (see recommended models below) |
*Fill in APIMart API Key, Base URL and model name*
**Important:**
* Base URL must include `/v1` suffix: `https://api.apimart.ai/v1`
* API Key must be obtained from APIMart console and start with `sk-`
* Model name must be the exact model ID (e.g., `gpt-4o`, `claude-sonnet-4-5-20250929`, etc.)
* Ensure your API key has sufficient balance
**Recommended Models:**
| Model Name | Model ID | Features |
| ----------------- | ------------------------------- | -------------------------------- |
| GPT-5 | `gpt-5` | Latest and most powerful |
| GPT-4o | `gpt-4o` or `chatgpt-4o-latest` | High-quality conversation |
| GPT-4o Mini | `gpt-4o-mini` | Fast and economical |
| Claude Sonnet 4.5 | `claude-sonnet-4-5-20250929` | Excellent for code and reasoning |
| Claude Haiku 4.5 | `claude-haiku-4-5-20251001` | Fast response |
| Gemini 2.0 Flash | `gemini-2.0-flash-exp` | Multimodal support |
**Performance Recommendations:**
* 💰 **Cost-effective:** `gpt-4o-mini`, `claude-haiku-4-5-20251001`
* 🚀 **High-performance:** `gpt-5`, `gpt-4o`, `claude-sonnet-4-5-20250929`
* ⚡ **Fast response:** `gemini-2.0-flash-exp`, `gpt-4o-mini`
### 2.3 Adjust Model Parameters (Optional)
You can adjust the following parameters as needed:
| Parameter | Description | Recommended Value |
| --------------- | -------------------------- | ------------------------------ |
| **Temperature** | Controls output randomness | 0.7 (creative) / 0.3 (precise) |
| **Max Tokens** | Maximum output length | 2000-4000 |
| **Top P** | Nucleus sampling parameter | 0.9 |
### 2.4 Save Configuration
1. Click the **Save** button at the bottom of the page
2. System will automatically test the connection
3. Success message will appear if configuration is correct
## Step 3: Configure Embedding Model (Optional)
AnythingLLM supports vector embeddings for document retrieval and knowledge base functionality.
### 3.1 Navigate to Embedding Settings
In the settings page:
1. Find **Embedding Preference** in the left menu
2. Click to enter embedding model configuration page
### 3.2 Configure Embedding Model
| Field | Value |
| ---------------------- | ---------------------------------------------------- |
| **Embedding Provider** | Select **Generic OpenAI** |
| **API Key** | Your APIMart API key (`sk-xxxxxxxxxxxx`) |
| **Base URL** | `https://api.apimart.ai/v1` |
| **Model** | `text-embedding-3-small` or `text-embedding-3-large` |
**Model Selection Recommendations:**
* `text-embedding-3-small` - Fast and economical, suitable for most scenarios
* `text-embedding-3-large` - Higher precision, suitable for scenarios requiring high retrieval quality
## Step 4: Create Workspace and Upload Documents
### 4.1 Create Workspace
1. Return to main interface
2. Click **+ New Workspace**
3. Enter workspace name (e.g., "Technical Documentation Assistant", "Customer Service Knowledge Base")
4. Click Create
### 4.2 Upload Documents
AnythingLLM supports various document formats:
**Supported Document Types:**
* 📄 **Text Documents** - .txt, .md, .pdf, .docx
* 💻 **Code Files** - .py, .js, .java, .cpp, etc.
* 🌐 **Web Pages** - Via URL scraping
* 📊 **Data Files** - .csv, .json, .xml
**Upload Steps:**
1. On the workspace page, click **Upload Documents**
2. Select files or drag and drop files into the upload area
3. Wait for document processing to complete
4. Documents will be automatically vectorized
**Document Processing:** Uploaded documents are automatically split into chunks and vectorized using the embedding model, stored in local database.
### 4.3 Manage Documents
On the document management page:
1. View all uploaded documents
2. Delete unnecessary documents
3. View document chunking details
4. Edit document metadata
## Step 5: Start Conversations
After configuration, you can start using AnythingLLM:
### 5.1 Basic Conversations
1. In the workspace, find the conversation input box
2. Enter your question or request
3. AI will generate responses based on your uploaded documents and APIMart models
### 5.2 Using Knowledge Base Features
AnythingLLM will automatically:
1. Analyze your question
2. Retrieve relevant content from uploaded documents
3. Generate accurate answers combining retrieved content and AI model
**Improve Retrieval Effectiveness:**
* Upload high-quality, structured documents
* Use clear, specific questions
* Regularly update and maintain knowledge base
### 5.3 Switch Workspaces
You can create multiple workspaces for different projects or topics:
1. Click workspace name in top left corner
2. Select other workspaces or create new ones
3. Each workspace has independent documents and conversation history
## Advanced Features
### 1. Agent Mode
AnythingLLM supports Agent functionality, allowing AI to:
* 🔍 **Search Web** - Get real-time information
* 🧮 **Perform Calculations** - Handle math and data analysis
* 📊 **Generate Charts** - Visualize data
* 🔗 **Call APIs** - Interact with external services
**Enable Agent Mode:**
1. Find **Agent Configuration** in workspace settings
2. Select tools and features to enable
3. Save configuration
### 2. Conversation History Management
* **Export Conversations** - Export conversations as text or JSON format
* **Search History** - Quickly find historical conversations
* **Delete Records** - Clean up unnecessary conversation history
### 3. Custom System Prompts
In workspace settings:
1. Find **System Prompt**
2. Customize AI's role and behavior
3. Example:
```
You are a professional technical support engineer, skilled at answering technical questions about products.
When answering, please:
1. Maintain professionalism and courtesy
2. Provide detailed step-by-step instructions
3. If uncertain, recommend contacting technical support
```
### 4. Multi-user Management (Docker Deployment Only)
If using Docker deployment:
* Create multiple user accounts
* Set different permission levels
* Manage workspace access permissions
### 5. API Access
AnythingLLM provides REST API for:
* Programmatic workspace access
* Upload and manage documents
* Send conversation requests
* Integrate into your applications
## FAQ
### Q1: Cannot connect to APIMart service?
**Solution:**
1. **Check Base URL**:
* Ensure it's `https://api.apimart.ai/v1` (includes `/v1`)
* Don't add extra paths or omit `/v1`
2. **Verify API Key**:
* Confirm API Key starts with `sk-`
* Check if key is valid in [APIMart Console](https://apimart.ai/keys)
3. **Check Network Connection**:
* Ensure access to `https://api.apimart.ai`
* Check firewall or proxy settings
### Q2: Documents not retrieving properly after upload?
**Solution:**
1. **Check Embedding Model Configuration**:
* Confirm embedding model is correctly configured
* Test embedding model connection
2. **Re-process Documents**:
* Delete and re-upload documents
* Check if document format is supported
3. **Adjust Retrieval Parameters**:
* Adjust similarity threshold in workspace settings
* Increase number of returned document chunks
### Q3: Slow conversation response?
**Solution:**
1. **Switch to Faster Models**:
* Use `gpt-4o-mini` instead of `gpt-4o`
* Use `gemini-2.0-flash-exp` for faster response
2. **Optimize Document Quantity**:
* Reduce number of documents in workspace
* Remove unnecessary large files
3. **Adjust Max Tokens**:
* Reduce maximum output length
* Use more concise prompts
### Q4: How to view API usage and costs?
Log in to [APIMart Console](https://apimart.ai/overview) to view:
* 📊 API call statistics
* 💰 Cost details
* 📈 Usage trend charts
* 🔍 Detailed request logs
### Q5: What deployment options does AnythingLLM support?
AnythingLLM supports multiple deployment options:
* 🖥️ **Desktop Application** - Windows, macOS, Linux
* 🐳 **Docker** - Self-hosted deployment
* ☁️ **Cloud Version** - AnythingLLM Cloud (coming soon)
## Use Case Examples
### 1. Enterprise Knowledge Base
**Configuration:**
* Model: `gpt-4o-mini` (cost-effective)
* Documents: Internal company documents, manuals, FAQs
* Function: Quick information lookup for employees
**Example Use Cases:**
* New employee onboarding
* Quick company policy lookup
* Technical documentation retrieval
### 2. Technical Documentation Assistant
**Configuration:**
* Model: `claude-sonnet-4-5-20250929` (excellent for code)
* Documents: API docs, technical specifications, codebase
* Function: Assist developers in finding technical information
**Example Use Cases:**
* API usage documentation queries
* Code example retrieval
* Technical question answering
### 3. Customer Service Knowledge Base
**Configuration:**
* Model: `gpt-4o` (high-quality conversation)
* Documents: Product manuals, FAQs, solutions
* Function: Quick customer question response
**Example Use Cases:**
* Automatic FAQ answering
* Product usage guidance
* Troubleshooting suggestions
### 4. Research and Learning Assistant
**Configuration:**
* Model: `gpt-5` (powerful understanding)
* Documents: Research papers, textbooks, notes
* Function: Assist in learning and research
**Example Use Cases:**
* Paper summarization and analysis
* Knowledge point explanation
* Learning path planning
## Features
Using AnythingLLM + APIMart, you can:
* 📚 **Private Knowledge Base** - Build secure private knowledge base locally
* 🔒 **Data Privacy** - All data stored locally, protecting privacy
* 🤖 **Multi-model Support** - Flexibly switch between different AI models
* 📄 **Multi-format Support** - Support various document formats
* 🎯 **Precise Retrieval** - Vector-based intelligent document retrieval
* 💬 **Contextual Conversation** - Maintain context in long conversations
* 🔧 **Highly Customizable** - Custom prompts, parameters, etc.
* 🌐 **Cross-platform** - Support Windows, macOS, Linux
## Data Security and Privacy
### Local Data Storage
AnythingLLM data storage approach:
* 📁 **Local File System** - Documents stored locally
* 🗄️ **Local Vector Database** - Vector indexes stored locally
* 💾 **Conversation History** - Conversation records stored locally
### API Call Security
* 🔐 **Encrypted Transmission** - All API calls use HTTPS encryption
* 🔑 **Key Protection** - API Key securely stored
* 🚫 **No Data Retention** - APIMart does not store your conversation content
**Privacy Notice:** While documents are stored locally, conversations and retrieved content sent to AI are transmitted to APIMart servers via API for processing. Please avoid uploading or querying content with sensitive information.
## Best Practices
### 1. Document Management
* **Regular Updates** - Keep document content current
* **Structured Organization** - Use clear folder structure
* **Naming Conventions** - Use meaningful file names
* **Delete Outdated** - Regularly clean up outdated documents
### 2. Prompt Optimization
**❌ Bad Prompt:**
```
You are an assistant
```
**✅ Good Prompt:**
```
You are a professional technical support assistant specializing in helping users resolve product-related technical issues.
When answering, please follow these principles:
1. Answer based on provided documentation; if information isn't available, clearly state so
2. Provide detailed step-by-step instructions with examples when necessary
3. Use clear, understandable language
4. For complex issues, recommend contacting the technical support team
```
### 3. Performance Optimization
* **Control Document Size** - Avoid uploading overly large individual files
* **Reasonable Chunking** - Use default document chunking settings
* **Choose Appropriate Model** - Select model based on task complexity
* **Monitor Usage** - Regularly check API usage
### 4. Workspace Planning
* **Divide by Project** - Create independent workspaces for different projects
* **Permission Management** - Set workspace permissions appropriately (Docker version)
* **Backup Data** - Regularly backup important workspaces
## Support & Help
If you encounter any issues:
* 📚 [APIMart Documentation](https://docs.apimart.ai)
* 📚 [AnythingLLM Official Documentation](https://docs.anythingllm.com/)
* 📚 [AnythingLLM GitHub](https://github.com/Mintplex-Labs/anything-llm)
* 💬 [Discord Community](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 Technical Support: [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
***
Register for APIMart now, get your API key, and build your private knowledge base in AnythingLLM!
# Using APIMart in ChatBox
Source: https://docs.apimart.ai/en/integrations/chat/chatbox
Detailed guide on how to configure and use APIMart API service in ChatBox desktop client. This guide will help you configure APIMart API in ChatBox to access rich AI model resources.
## Prerequisites
Before you begin, please ensure:
1. **ChatBox is installed**
Download and install the version suitable for your operating system from [ChatBox GitHub](https://github.com/Bin-Huang/chatbox) or visit [ChatBox Official Website](https://chatboxai.app/)
2. **APIMart API Key obtained**
Log in to [APIMart Console](https://apimart.ai/keys) to get your API key (starts with `sk-`)
**Tip:** If you don't have an APIMart account yet, please register at [APIMart](https://apimart.ai) and obtain an API key first.
## Step 1: Launch ChatBox and Start Configuration
When launching ChatBox for the first time or adding a new AI provider:
1. Launch the ChatBox application
2. If it's your first time, a configuration wizard will appear automatically
3. Click the **"Use your own API Key or local model"** button
4. If already configured, click the **⚙️ Settings** icon in the bottom left corner, or use the shortcut `Ctrl+,` (Windows/Linux) / `Cmd+,` (macOS)
*ChatBox configuration wizard, select to use your own API Key*
## Step 2: Configure APIMart API
### 2.1 Select AI Model Provider
In the settings page:
1. Find the **AI Provider** setting
2. Select **OpenAI API** (for GPT series models), **Claude API** (for Claude series models), or **Gemini API** (for Gemini series models) from the dropdown menu
*ChatBox settings page, select OpenAI API as provider*
### 2.2 Configure API Information
After selecting OpenAI API, fill in the following configuration:
| Field | Value |
| ------------------------------ | ---------------------------------------- |
| **API Key** | Your APIMart API key (`sk-xxxxxxxxxxxx`) |
| **API Host** or **API Domain** | `https://api.apimart.ai` |
After selecting Claude API, fill in the following configuration:
| Field | Value |
| ------------------------------ | ---------------------------------------- |
| **API Key** | Your APIMart API key (`sk-xxxxxxxxxxxx`) |
| **API Host** or **API Domain** | `https://api.apimart.ai/v1` |
After selecting Gemini API, fill in the following configuration:
| Field | Value |
| ------------------------------ | ---------------------------------------- |
| **API Key** | Your APIMart API key (`sk-xxxxxxxxxxxx`) |
| **API Host** or **API Domain** | `https://api.apimart.ai/` |
*Fill in APIMart's API Key and API Host*
**Important:**
* When using OpenAI API, API Host should be `https://api.apimart.ai` (without `/v1` suffix)
* When using Claude API, API Host should be `https://api.apimart.ai/v1` (with `/v1` suffix)
* When using Gemini API, API Host should be `https://api.apimart.ai/` (without `/v1` suffix)
* API Key must be obtained from APIMart console and start with `sk-`
* Ensure your API key has sufficient balance
### 2.3 Select Model
After configuration, select the model you want to use from the **Model** dropdown:
**Recommended Models:**
| Model Name | Model ID | Features |
| ----------------- | ------------------------------- | ------------------------ |
| GPT-5 | `gpt-5` | Latest and most powerful |
| GPT-4o | `gpt-4o` or `chatgpt-4o-latest` | High-quality chat |
| GPT-4o Mini | `gpt-4o-mini` | Fast and economical |
| Claude Sonnet 4.5 | `claude-sonnet-4-5-20250929` | Excellent for code |
| Claude Haiku 4.5 | `claude-haiku-4-5-20251001` | Fast response |
| Gemini 2.0 Flash | `gemini-2.0-flash-exp` | Multimodal support |
**Special Instructions for Using Claude Models:**
If you choose to use Claude models (such as `claude-sonnet-4-5-20250929` or `claude-haiku-4-5-20251001`), you need the following additional configuration:
1. **Switch to Claude API Provider**:
* Change the **AI Provider** to **Claude API** in settings
* Keep API Host as `https://api.apimart.ai/v1`
* Use your APIMart API key (`sk-xxxxxxxxxxxx`)
2. **Or Add Custom Request Headers** (if using OpenAI API provider):
* Some versions of ChatBox support adding custom Headers
* Add the request header in advanced settings: `anthropic-version: 2023-06-01`
**Recommended Approach:** Use **OpenAI API** for GPT series models, **Claude API** for Claude series models, and **Gemini API** for Gemini series models.
*Select your desired AI model from the list*
**Performance Recommendations:**
* 💰 **Cost-effective:** `gpt-4o-mini`, `claude-haiku-4-5-20251001`
* 🚀 **High-performance:** `gpt-5`, `gpt-4o`, `claude-sonnet-4-5-20250929`
* ⚡ **Fast response:** `gemini-2.0-flash-exp`, `gpt-4o-mini`
## Step 3: Start Using
After configuration, you can start using ChatBox to chat with AI:
1. Return to the main interface
2. Type your question or requirement in the input box
3. Press `Enter` or click the send button
4. AI will generate a reply using APIMart's models
*ChatBox chat interface, start conversing with AI*
### Adjust Model Parameters (Optional)
You can adjust the following parameters as needed:
| Parameter | Description | Recommended Value |
| --------------- | -------------------------- | ------------------------------ |
| **Temperature** | Controls output randomness | 0.7 (creative) / 0.3 (precise) |
| **Max Tokens** | Maximum output length | 2000-4000 |
| **Top P** | Nucleus sampling parameter | 0.9 |
## Advanced Features
### Multi-Session Management
ChatBox supports creating multiple conversation sessions:
1. Click the **New Chat** button
2. Create independent sessions for different tasks
3. Switch between conversations in the left session list
### Save and Export Conversations
1. Right-click on a conversation session
2. Select **Export** option
3. Export as Markdown, JSON, or other formats
### Using Prompt Templates
1. Find **Prompts** settings in the settings menu
2. Save commonly used prompt templates
3. Quickly invoke preset prompts in conversations
## FAQ
### Q1: Cannot connect to APIMart service?
**Solution:**
1. **Check API Host**:
* Ensure it's `https://api.apimart.ai`
* Don't add `/v1` or other paths
2. **Verify API Key**:
* Confirm API Key starts with `sk-`
* Check if the key is valid in [APIMart Console](https://apimart.ai/keys)
3. **Check Network Connection**:
* Ensure you can access `https://api.apimart.ai`
* You may need to configure a proxy if in China
### Q2: APIMart models not showing in model list?
**Solution:**
1. **Manually Enter Model Name**:
* Directly type the model ID in the model input box
* For example: `gpt-4o`, `gpt-4o-mini`, `claude-sonnet-4-5-20250929`
2. **Refresh Model List**:
* Restart ChatBox application
* Reconfigure API information
### Q3: Error messages during conversation?
**Common errors and solutions:**
| Error Message | Cause | Solution |
| --------------------------- | ---------------------------- | ------------------------------------------ |
| `401 Unauthorized` | Invalid or expired API Key | Re-obtain API Key and update configuration |
| `429 Too Many Requests` | Request rate limit exceeded | Wait a moment and retry |
| `500 Internal Server Error` | Temporary server issue | Wait a few minutes and retry |
| `insufficient_quota` | Insufficient account balance | Top up in the console |
### Q4: How to view API usage and costs?
Log in to [APIMart Console](https://apimart.ai/overview) to view:
* 📊 API call statistics
* 💰 Cost details
* 📈 Usage trend charts
* 🔍 Detailed request logs
### Q5: Which platforms does ChatBox support?
ChatBox supports multiple platforms:
* 🪟 **Windows** - Windows 10/11
* 🍎 **macOS** - macOS 10.15+
* 🐧 **Linux** - Major distributions
* 🌐 **Web** - Browser version
## Usage Tips
### 1. Keyboard Shortcuts
Utilize ChatBox keyboard shortcuts for efficiency:
| Shortcut | Function |
| ------------------ | -------------------- |
| `Ctrl/Cmd + Enter` | Send message |
| `Ctrl/Cmd + N` | New chat |
| `Ctrl/Cmd + K` | Search conversations |
| `Ctrl/Cmd + ,` | Open settings |
| `Ctrl/Cmd + /` | Show keyboard help |
### 2. Optimize Prompts
Write better prompts for better responses:
**❌ Poor Prompt:**
```
Write code for me
```
**✅ Good Prompt:**
```
Please help me write a Python function that:
1. Takes a list of strings as input
2. Filters out strings shorter than 3 characters
3. Returns results sorted alphabetically
Please include detailed comments and usage examples
```
### 3. Leverage Conversation History
ChatBox saves conversation history:
* AI remembers context from the current session
* Can continue asking based on previous responses
* Suitable for deep discussions and iterations
### 4. Switch Models
Switch to appropriate models for different tasks:
* **Writing tasks** - Use `gpt-4o` or `claude-sonnet-4-5`
* **Coding tasks** - Use `claude-sonnet-4-5`
* **Quick Q\&A** - Use `gpt-4o-mini`
* **Multimodal** - Use `gemini-2.0-flash-exp`
## Features
Using ChatBox + APIMart, you can:
* 💬 **Smooth Conversations** - Real-time streaming output for smoother experience
* 🎯 **Multi-Session Management** - Manage multiple independent conversations simultaneously
* 💾 **Local Storage** - Conversation records saved locally to protect privacy
* 📤 **Export Conversations** - Support exporting in multiple formats
* 🎨 **Clean Interface** - Simple and beautiful user interface
* 🔒 **Open Source & Free** - Completely open source and free to use
* 🌍 **Cross-Platform** - Supports Windows, macOS, Linux
* 🚀 **Excellent Performance** - Lightweight application, runs smoothly
## Support & Help
If you encounter any issues:
* 📚 [APIMart Documentation](https://docs.apimart.ai)
* 📚 [ChatBox GitHub](https://github.com/Bin-Huang/chatbox)
* 💬 [Discord Community](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 Technical Support: [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
***
Register for APIMart now, get your API key, and start your AI journey in ChatBox!
# Using APIMart in Cherry Studio
Source: https://docs.apimart.ai/en/integrations/chat/cherry-studio
Detailed guide on how to configure and use APIMart API service in Cherry Studio desktop client. This guide will help you configure APIMart API in Cherry Studio to access rich AI model resources.
## Prerequisites
Before you begin, please ensure:
1. **Cherry Studio is installed**\
Download and install the version suitable for your operating system from [Cherry Studio Official Website](https://cherry-ai.com/)
2. **APIMart API Key obtained**\
Log in to [APIMart Console](https://apimart.ai/keys) to get your API key (starts with `sk-`)
**Tip:** If you don't have an APIMart account yet, please register at [APIMart](https://apimart.ai) and obtain an API key first.
## Step 1: Open Cherry Studio Settings
After launching Cherry Studio, navigate to the settings page:
1. Click the **⚙️ Settings** icon (gear icon) in the top right corner
2. Or use keyboard shortcuts:
* Windows/Linux: `Ctrl + ,`
* macOS: `Cmd + ,`
*Cherry Studio main interface, click the gear icon in the top right to access settings*
## Step 2: Add APIMart Model Platform
### 2.1 Access Model Service Management
In the settings page:
1. Find the **Model Service** option in the left menu
2. Click to enter model service management page
*Find "Model Service" option in the left menu of settings page*
### 2.2 Add APIMart Provider
1. At the bottom of the model service page, click the **"+ Add"** button
*Click "+ Add" to open the add provider dialog*
2. In the **"Add Provider"** dialog, fill in:
* **Provider Name**: `APIMart` (customizable)
* **Provider Type**: Select `OpenAI`
3. Click the **"Confirm"** button
### 2.3 Configure APIMart API Information
After adding the provider, fill in the API information in the right configuration area:
| Field | Value |
| ----------- | ---------------------------------------- |
| **API Key** | Your APIMart API key (`sk-xxxxxxxxxxxx`) |
| **API URL** | `https://api.apimart.ai` |
**Important:**
* API URL must be `https://api.apimart.ai` (do not include `/v1` or other paths)
* API Key must be obtained from APIMart console and start with `sk-`
* After filling in, you can click the **"Test"** button to test the connection
*Fill in API key and API URL, ensure APIMart provider status is ON (green switch)*
## Step 3: Add and Manage Models
### 3.1 Open Model Management
After configuring the APIMart provider:
1. Ensure the APIMart provider switch in the top right is **ON** (green)
2. In the right configuration area, find the **"Models"** section
3. Click the **"Manage"** button to open the model selection window
*Click "Manage" button to open APIMart model selection window*
### 3.2 Add Desired Models
In the model selection window:
1. Use the search box to find specific models
2. Use the category tabs at the top to filter: **All**, **Reasoning**, **Vision**, **Web**, **Free**, **Embedding**, **Rerank**, **Tool**
3. Find the models you want and click the **+** button on the right to add:
* `gpt-4o` / `chatgpt-4o` - OpenAI GPT-4o model
* `gpt-4o-mini` - Faster and more economical version
* `claude-3` series - Claude 3 models (with multiple variants)
* `claude_code_sonnet-4` - Claude Code Sonnet 4
* `claude_code_haiku-4` - Claude Code Haiku 4
* `gemini-2.0-flash-exp` - Google Gemini 2.0 Flash
*Added models will appear on the right, can be expanded to view specific variants*
4. After adding all desired models, close the model selection window
**Recommended Models:**
* 💰 **Cost-effective:** `gpt-4o-mini`, `claude_code_haiku-4`
* 🚀 **High-performance:** `gpt-4o` / `chatgpt-4o`, `claude_code_sonnet-4`
* 🎨 **Multimodal:** `claude-3` series, `gemini-2.0-flash-exp`
## Step 4: Start Chatting
After configuration, you can start using it:
1. Return to the main interface, click the **"+"** at the top or select an existing chat
2. At the top of the chat page, click the model selector
3. Select a model under the **APIMart** provider
4. Start chatting with AI!
*Create a new chat and select APIMart provider and model*
*Cherry Studio chat interface example*
## FAQ
### Q1: Cannot connect to APIMart service?
**Solution:**
1. **Check Base URL**:
* Ensure Base URL is `https://api.apimart.ai`
* Do not add `/v1` suffix
2. **Verify API Key**:
* Confirm API Key is correct and starts with `sk-`
* Check if the key is valid in [APIMart Console](https://apimart.ai/keys)
3. **Check Network Connection**:
* Ensure you can access `https://api.apimart.ai`
* You may need to configure a proxy if in China
### Q2: Model list is empty or cannot refresh?
**Solution:**
1. **Manually Add Models**:
* If auto-refresh fails, you can manually add common models
* In model management, manually enter model names (e.g., `gpt-4o`)
2. **Check API Permissions**:
* Confirm your API Key has permission to access the model list
* Contact APIMart support to check account status
### Q3: Error messages during conversation?
**Common errors and solutions:**
| Error Message | Cause | Solution |
| --------------------------- | ---------------------------- | ------------------------------------------ |
| `401 Unauthorized` | Invalid or expired API Key | Re-obtain API Key and update configuration |
| `429 Too Many Requests` | Request rate limit exceeded | Wait a moment and retry |
| `500 Internal Server Error` | Temporary server issue | Wait a few minutes and retry |
| `insufficient_quota` | Insufficient account balance | Top up in the console |
### Q4: How to view API usage and costs?
Log in to [APIMart Console](https://apimart.ai/overview) to view:
* 📊 API call statistics
* 💰 Cost details
* 📈 Usage trend charts
## Features
Using Cherry Studio + APIMart, you can:
* 💬 **Multi-model Conversations** - Use different AI models in the same interface
* 🖼️ **Image Understanding** - Multi-modal conversations with image input support
* 📝 **Context Management** - Intelligent management of conversation history and context
* 🎨 **Custom Prompts** - Create and manage prompt templates
* 📊 **Export Conversations** - Export conversation records to Markdown and other formats
* 🔄 **Model Comparison** - Use multiple models simultaneously and compare outputs
## Support & Help
If you encounter any issues:
* 📚 [APIMart Documentation](https://docs.apimart.ai)
* 💬 [Discord Community](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 Technical Support: [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
***
Register for APIMart now, get your API key, and start your AI journey!
# Using APIMart in CC-Switch
Source: https://docs.apimart.ai/en/integrations/dev-tool/cc-switch
A detailed guide on configuring and using APIMart API services in CC-Switch, enabling you to access multiple AI models for assisted programming with simple configuration.
## Introduction
CC-Switch is an open-source desktop application that unifies the management of API provider configurations across multiple AI coding CLI tools such as Claude Code, Codex, and Gemini CLI.
It turns tedious configuration file editing into just a few clicks in a GUI — once a provider is added, you can switch between API services instantly, with no need to edit configuration files by hand.
By connecting APIMart through CC-Switch, you can easily configure the APIMart service for Claude Code and Codex, and switch freely between multiple providers.
## Prerequisites
Before you begin, make sure you have:
1. **Installed a supported CLI tool**
At least one supported CLI tool installed, such as [Claude Code](/en/integrations/dev-tool/claude-code) or [Codex CLI](/en/integrations/dev-tool/codex-cli)
2. **Obtained an APIMart API Key**
Log in to the [APIMart Console](https://apimart.ai/keys) to get your API key (starts with `sk-`)
**Tip:** If you don't have an APIMart account yet, please register at [APIMart](https://apimart.ai) first and obtain your API key.
## Step 1: Install CC-Switch
Choose the installation method based on your operating system:
Install via Homebrew (recommended):
```bash theme={null}
brew tap farion1231/ccswitch
brew install --cask cc-switch
```
You can also download the `.dmg` installer from [GitHub Releases](https://github.com/farion1231/cc-switch/releases). CC-Switch is signed and notarized by Apple, so it can be installed directly (requires macOS 12 or later).
Download the `.msi` installer or the portable `.zip` from [GitHub Releases](https://github.com/farion1231/cc-switch/releases).
Requires Windows 10 or later.
Download the appropriate package from [GitHub Releases](https://github.com/farion1231/cc-switch/releases):
* Debian / Ubuntu: `.deb` package
* Fedora / RHEL: `.rpm` package
* Universal: `.AppImage` format
* Arch Linux: `paru -S cc-switch-bin`
When CC-Switch is launched for the first time, it automatically detects CLI tools installed on your machine and can import existing configurations as the default providers.
## Step 2: Add the APIMart Provider
At the top of the CC-Switch main window you can switch between different CLI tool groups. Refer to the steps below based on the tool you want to configure.
**1. Switch to the Claude Code group**
Select **Claude Code** at the top of the main window.
**2. Open the Add Provider panel**
Click the **+** button at the top-right corner of the main window.
**3. Fill in the provider details**
Fill out the form as follows:
| Field | Value | Description |
| ---------------- | ------------------------ | ---------------------------------------- |
| **Name** | `APIMart` | Custom label for easy identification |
| **Endpoint URL** | `https://api.apimart.ai` | APIMart API base URL |
| **API Key** | `sk-xxxxxxxxxxxx` | Your APIMart API key |
| **API Format** | `Anthropic Messages` | Keep the default Anthropic-native format |
**4. Save the configuration**
Click **Add** to save. APIMart will appear in the provider list.
**1. Switch to the Codex group**
Select **Codex** at the top of the main window.
**2. Open the Add Provider panel**
Click the **+** button at the top-right corner of the main window.
**3. Fill in the provider details**
A Codex provider is configured through two blocks:
Fill in the API key in the **auth.json** block:
```json theme={null}
{
"OPENAI_API_KEY": "sk-xxxxxxxxxxxx"
}
```
Fill in the provider config in the **config.toml** block:
```toml theme={null}
model = "gpt-5.5"
model_provider = "apimart"
[model_providers.apimart]
name = "APIMart"
base_url = "https://api.apimart.ai/v1"
wire_api = "responses"
requires_openai_auth = true
```
**4. Save the configuration**
Name the provider (e.g., `APIMart`) and click **Add** to save. CC-Switch will automatically validate both the JSON and the TOML.
**About the endpoint URL:** Claude Code uses the Anthropic-native format with the URL `https://api.apimart.ai` (no `/v1`); Codex uses the OpenAI-compatible format with the URL `https://api.apimart.ai/v1` (with
`/v1`). Do not mix them up.
## Step 3: Switch Providers
Once added, you can switch between APIMart and other providers at any time:
### Switch in the main window
1. Select **APIMart** in the provider list
2. Click the **Enable** (or **Use**) button
3. A "Switched successfully" toast confirms the change
### Switch from the system tray
CC-Switch stays in the system tray, so you can switch without opening the main window:
1. Click the CC-Switch icon in the system tray
2. Click the target provider name in the menu — it takes effect immediately
**About activation:** Claude Code supports hot switching — new sessions pick up the new configuration automatically. After switching for Codex, you need to restart the terminal or Codex for the change to take effect.
## Supported Models
After switching to the APIMart provider, you can use a variety of models in the corresponding CLI tool:
| Model ID | Strengths | Recommended Use Cases |
| ------------------- | ----------------------- | ------------------------------------ |
| `claude-opus-4-6` | Strongest overall | Complex architecture, hard debugging |
| `claude-sonnet-4-6` | Balanced perf & speed | Day-to-day coding, code generation |
| `gpt-5.5` | Excellent coding skills | Complex engineering tasks |
| `gpt-4o` | High performance, fast | Everyday coding, fast iteration |
In Claude Code, use the `/model` command to switch models; in Codex, use the `/model` command as well. For the full model list, see the [Claude Code guide](/en/integrations/dev-tool/claude-code) and the [Codex CLI
guide](/en/integrations/dev-tool/codex-cli).
## FAQ
### Q1: Switching providers doesn't take effect?
* **Claude Code**: Supports hot switching — start a new session; if it still doesn't work, restart Claude Code
* **Codex**: After switching, restart the terminal or Codex
### Q2: API key reported as invalid?
1. Make sure the API key starts with `sk-` and is copied in full with no extra whitespace
2. Go to the [APIMart Console](https://apimart.ai/keys) to confirm the key is active
3. Check that the endpoint URL is correct (Claude Code uses `https://api.apimart.ai`, Codex uses `https://api.apimart.ai/v1`)
### Q3: Format error when adding a Codex provider?
CC-Switch validates `auth.json` (JSON syntax) and `config.toml` (TOML syntax). Check that:
* Brackets, quotes, and commas in the JSON are complete
* No full-width / smart quotes are used
* Field names in the TOML are spelled correctly
### Q4: Which files does CC-Switch modify?
CC-Switch writes to the configuration files of each tool:
* **Claude Code**: `~/.claude/settings.json`
* **Codex**: `~/.codex/config.toml` and `~/.codex/auth.json`
CC-Switch automatically backs up these files before switching, so you don't need to edit them by hand.
### Q5: How do I view API usage and billing?
Log in to the [APIMart Console](https://apimart.ai/overview) to view API call statistics, token consumption details, and cost trends.
## Support and Help
If you run into any issues while using CC-Switch:
* 📚 [APIMart Documentation Center](https://docs.apimart.ai)
* 📚 [CC-Switch Project Page](https://github.com/farion1231/cc-switch)
* 💬 [Discord Community](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 Technical support: [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
***
Sign up for APIMart now, grab your API key, and manage multiple AI coding tools effortlessly in CC-Switch!
# Using APIMart in Claude Code
Source: https://docs.apimart.ai/en/integrations/dev-tool/claude-code
A detailed guide on configuring and using APIMart API services in Claude Code CLI, enabling you to access multiple AI models for assisted programming with simple configuration.
## Prerequisites
Claude Code is a command-line AI programming assistant by Anthropic that supports direct AI conversation, code generation, and debugging in the terminal.
By connecting to APIMart, you can use multiple models including GPT, Claude, and Gemini within Claude Code.
Before you begin, make sure you have:
1. **Obtained an APIMart API Key**
Log in to the [APIMart Console](https://apimart.ai/keys) to get your API key (starts with `sk-`)
**Tip:** If you don't have an APIMart account yet, please register at [APIMart](https://apimart.ai) first and obtain your API key.
## Step 1: Install Claude Code
Choose any of the following methods to install:
Install with the official script:
```bash theme={null}
curl -fsSL https://claude.ai/install.sh | bash
```
Or install via Homebrew:
```bash theme={null}
brew install --cask claude-code
```
If you encounter permission issues, add `sudo` before the command.
**PowerShell:**
```powershell theme={null}
irm https://claude.ai/install.ps1 | iex
```
**CMD:**
```cmd theme={null}
curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
```
If you have Node.js 18 or newer installed, you can install via npm:
```bash theme={null}
npm install -g @anthropic-ai/claude-code
```
Works on all operating systems.
### Verify Installation
After installation, run the following command to confirm:
```bash theme={null}
claude --version
```
If a version number is displayed (e.g., `1.x.x`), the installation was successful.
## Step 2: Configure APIMart API
Three configuration methods are available. Choose the one that suits your workflow.
### Method 1: Edit settings.json (Recommended)
The most stable approach — configure once and it persists.
**1. Locate the configuration directory:**
* Windows: Press `Win + R`, enter `%userprofile%\.claude`
* macOS: Press `Command + Shift + G`, enter `~/.claude`
* Linux: Navigate to `~/.claude`
If the directory doesn't exist, run `claude` once in the terminal and press `Ctrl + C` to exit — the directory will be created automatically.
**2. Create or edit the `settings.json` file:**
```json theme={null}
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.apimart.ai",
"ANTHROPIC_AUTH_TOKEN": "sk-xxxxxxxxxxxx",
"ANTHROPIC_MODEL": "claude-opus-5",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
}
}
```
| Parameter | Description |
| ------------------------------------------ | ------------------------------------------------------ |
| `ANTHROPIC_BASE_URL` | APIMart API address, fixed as `https://api.apimart.ai` |
| `ANTHROPIC_AUTH_TOKEN` | Your APIMart API key (starts with `sk-`) |
| `ANTHROPIC_MODEL` | Default model to use, choose from the model list below |
| `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | Set to `1` to reduce non-essential network requests |
Save the file and restart Claude Code to apply.
### Method 2: Permanent Environment Variables
Write configuration to system environment so all terminal windows load it automatically.
```bash theme={null}
echo 'export ANTHROPIC_BASE_URL="https://api.apimart.ai"' >> ~/.zshrc
echo 'export ANTHROPIC_API_KEY="sk-xxxxxxxxxxxx"' >> ~/.zshrc
echo 'export ANTHROPIC_MODEL="claude-opus-5"' >> ~/.zshrc
source ~/.zshrc
```
```bash theme={null}
echo 'export ANTHROPIC_BASE_URL="https://api.apimart.ai"' >> ~/.bashrc
echo 'export ANTHROPIC_API_KEY="sk-xxxxxxxxxxxx"' >> ~/.bashrc
echo 'export ANTHROPIC_MODEL="claude-opus-5"' >> ~/.bashrc
source ~/.bashrc
```
**Option A: GUI Settings**
1. Right-click "This PC" → "Properties" → "Advanced system settings" → "Environment Variables"
2. Add new user variables:
* `ANTHROPIC_BASE_URL` = `https://api.apimart.ai`
* `ANTHROPIC_API_KEY` = `sk-xxxxxxxxxxxx`
* `ANTHROPIC_MODEL` = `claude-opus-5`
3. Restart the terminal
**Option B: PowerShell Commands**
```powershell theme={null}
[System.Environment]::SetEnvironmentVariable('ANTHROPIC_BASE_URL', 'https://api.apimart.ai', 'User')
[System.Environment]::SetEnvironmentVariable('ANTHROPIC_API_KEY', 'sk-xxxxxxxxxxxx', 'User')
[System.Environment]::SetEnvironmentVariable('ANTHROPIC_MODEL', 'claude-opus-5', 'User')
```
### Method 3: Temporary Environment Variables
Suitable for quick testing — configuration is lost when the terminal is closed.
```bash theme={null}
export ANTHROPIC_API_KEY="sk-xxxxxxxxxxxx"
export ANTHROPIC_MODEL="claude-opus-5"
export ANTHROPIC_BASE_URL="https://api.apimart.ai"
claude
```
```powershell theme={null}
$env:ANTHROPIC_API_KEY="sk-xxxxxxxxxxxx"
$env:ANTHROPIC_MODEL="claude-opus-5"
$env:ANTHROPIC_BASE_URL="https://api.apimart.ai"
claude
```
```cmd theme={null}
set ANTHROPIC_API_KEY=sk-xxxxxxxxxxxx
set ANTHROPIC_MODEL=claude-opus-5
set ANTHROPIC_BASE_URL=https://api.apimart.ai
claude
```
Temporary environment variables only work in the current terminal window. You'll need to set them again after switching windows or closing the terminal.
## Step 3: Start Using
### Verify Configuration
Launch Claude Code and send a simple message to confirm:
```bash theme={null}
claude "Hello"
```
If you receive an AI response, the configuration is successful. If you see `401`, `403`, or other errors, refer to the FAQ below.
### Usage Modes
Claude Code offers two interaction modes:
* **Interactive mode**: Run `claude` for continuous conversation, ideal for complex tasks
* **Single command**: Run `claude "your question"` for a one-off response, ideal for quick queries
### Supported Models
APIMart supports the full Claude model series. You can flexibly switch based on your needs:
| Model Name | Features | Recommended Use |
| ---------------------------- | ------------------------------ | ----------------------------------------- |
| `claude-opus-5` | Next-generation flagship | Complex architecture, difficult debugging |
| `claude-opus-4-6` | Strong overall capability | Complex architecture, difficult debugging |
| `claude-sonnet-4-6` | Balanced performance and speed | Daily programming, code generation |
| `claude-opus-4-5-20251101` | Advanced reasoning | Complex code, deep analysis |
| `claude-sonnet-4-5-20250929` | Excellent code capability | Algorithm design, code optimization |
| `claude-haiku-4-5-20251001` | Ultra-fast response | Quick Q\&A, code snippets |
All models above support a Thinking (extended reasoning) version — append `-thinking` to the model ID, e.g., `claude-opus-4-6-thinking`. Thinking mode is ideal for complex tasks requiring deep reasoning.
**Model Recommendations:**
* 🚀 **High Performance:** `claude-opus-5` — For the most complex code and architecture challenges
* ⚖️ **Balanced Performance:** `claude-sonnet-4-6` — For daily programming
* ⚡ **Fast Response:** `claude-haiku-4-5-20251001` — When you need instant feedback
* 🧠 **Deep Thinking:** `claude-opus-5-thinking` — When deep reasoning is needed
To switch models, use the `/model` command in interactive mode, or modify the `ANTHROPIC_MODEL` field in your configuration and restart.
### Common Commands
Here are frequently used commands and shortcuts in Claude Code:
| Command | Description |
| ------------------- | -------------------------------- |
| `claude` | Enter interactive mode |
| `claude "question"` | Single query |
| `claude --version` | Check version |
| `/model` | Switch model in interactive mode |
| `/help` | View help information |
| `Ctrl + C` | Exit interactive mode |
## FAQ
### Q1: Still seeing the login selection page after configuration?
If "Select login method" still appears after startup, the configuration hasn't taken effect.
**Troubleshooting steps:**
1. **Using settings.json**: Check if the file path is correct
* Windows: `C:\Users\\.claude\settings.json`
* macOS / Linux: `~/.claude/settings.json`
2. **Using environment variables**: Make sure you launched Claude Code from the **same terminal window** where you set the variables
3. **Check JSON format**: Ensure brackets, commas, and quotes are all correct
### Q2: Getting 401 / 403 errors?
| Error Code | Meaning | Solution |
| ------------------ | --------------------------------------- | ------------------------------------------------------------- |
| `401 Unauthorized` | API key missing or invalid | Check if the key is correct and starts with `sk-` |
| `403 Forbidden` | Insufficient permissions or expired key | Go to [Console](https://apimart.ai/keys) to verify key status |
Also ensure `ANTHROPIC_BASE_URL` is set to `https://api.apimart.ai`, not the official Anthropic address.
### Q3: "Unable to connect" error?
This means Claude Code failed to connect to the API service.
1. Check your network connection
2. Verify `ANTHROPIC_BASE_URL` is configured correctly
3. If using a proxy, ensure it allows access to `api.apimart.ai`
### Q4: "Auth conflict" error?
If you see a message like:
```
Auth conflict: Both a token (claude.ai) and an API key (ANTHROPIC_API_KEY) are set.
```
This means you're logged into claude.ai and have an API Key set at the same time, causing a conflict.
**Solution:** Run `/logout` in Claude Code interactive mode to sign out of claude.ai, keeping only the API Key configuration.
### Q5: max\_tokens error when using non-Claude models?
If you see an error like:
```
max_tokens is too large: 32000. This model supports at most 16384 completion tokens.
```
This is because Claude Code sends requests with Claude model parameters by default (32000 tokens), while some non-Claude models (e.g., `gpt-4o`) have lower token limits.
**Solution:** Switch to a Claude model (e.g., `claude-sonnet-4-6`), which is natively compatible with Claude Code and won't cause this issue.
### Q6: Slow response?
1. Switch to a faster model (e.g., `claude-haiku-4-5-20251001` or `claude-sonnet-4-6`)
2. Shorten your prompts to reduce context length
3. Check your network conditions
### Q7: How to switch models?
Two ways:
1. **In interactive mode**: Enter the `/model` command
2. **Edit configuration**: Change the `ANTHROPIC_MODEL` field in `settings.json` or environment variables, then restart Claude Code
### Q8: Does Claude Code automatically read local files?
No. Claude Code requires you to explicitly reference files, and it will ask for confirmation before performing sensitive operations. It's recommended to use it in dedicated project directories.
### Q9: How to analyze local files with Claude Code?
In interactive mode, you can reference files by:
* Entering the file path directly
* Dragging files into the terminal window
* Copy-pasting file content
### Q10: How to check usage and costs?
Log in to the [APIMart Console](https://apimart.ai/overview) to view:
* API call statistics
* Token consumption details
* Cost statistics and trends
## Support
If you encounter any issues:
* 📚 [APIMart Documentation](https://docs.apimart.ai)
* 💬 [Discord Community](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 Technical Support: [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
***
Sign up for APIMart now, get your API key, and experience multi-model programming assistant in Claude Code!
# Integrate APIMart with Cline in VSCode
Source: https://docs.apimart.ai/en/integrations/dev-tool/cline
A detailed guide on how to configure APIMart API service using the Cline extension in Visual Studio Code. This guide will help you use APIMart's AI models through Cline for code development, debugging, and optimization in VSCode.
## Introduction
Cline (formerly Claude Dev) is a powerful VSCode extension that allows developers to interact with AI assistants directly in the editor, performing tasks such as code writing, debugging, and refactoring. By configuring the APIMart API, you can use various advanced AI models in Cline.
## Prerequisites
Before you begin, please ensure:
1. **Visual Studio Code is installed**\
Download and install VSCode from the [official website](https://code.visualstudio.com/)
2. **Cline extension is installed**\
Search for "Cline" in the VSCode extension marketplace and install it
3. **APIMart API key obtained**\
Log in to the [APIMart Console](https://apimart.ai/keys) to get your API key (starts with `sk-`)
**Tip:** If you don't have an APIMart account yet, please register at [APIMart](https://apimart.ai) first and obtain an API key.
## Step 1: Install Cline Extension
### 1.1 Open Extension Marketplace
In VSCode:
1. Click the **Extensions** icon in the left activity bar (or press `Ctrl+Shift+X` / `Cmd+Shift+X`)
2. Type **Cline** in the search box
3. Find the Cline extension (by Cline)
4. Click the **Install** button
### 1.2 Verify Installation
After installation:
1. The **Cline** icon (robot head) will appear in the left activity bar
2. Click the icon to open the Cline sidebar
3. On first open, you'll see the welcome message "Hi, I'm Cline"
4. Two options are displayed:
* **Get Started for Free** - Use the official free trial
* **Use your own API key** - Use your own API key
*Search and install Cline in the VSCode extension marketplace*
## Step 2: Configure APIMart API
### 2.1 Choose to Use Your Own API Key
On the Cline welcome screen:
1. Click the **Use your own API key** button
2. This will open the API configuration interface
*Cline welcome screen, select "Use your own API key" to use APIMart*
**Tip:** If you've configured before, you can click the **Settings** (gear icon) at the top of the Cline sidebar to access configuration.
### 2.2 Configure API Provider
In the Settings interface:
1. Expand the **API Configuration** section
2. Select **OpenAI Compatible** from the **API Provider** dropdown
3. This will display OpenAI compatible configuration options
**Important:** APIMart is fully compatible with the OpenAI API format, so selecting "OpenAI Compatible" is appropriate.
### 2.3 Fill in API Configuration
Fill in the following configuration information:
| Setting | Value | Description |
| ----------------------------- | --------------------------------------- | ------------------------- |
| **API Provider** | `OpenAI Compatible` | Select from dropdown |
| **Base URL** | `https://api.apimart.ai/v1` | APIMart API base URL |
| **OpenAI Compatible API Key** | `sk-xxxxxxxxxxxx` | Your APIMart API key |
| **Model ID** | `gpt-5` or `claude-sonnet-4-5-20250929` | Enter the model ID to use |
*Configure API Provider, Base URL, API Key, and Model ID in the Settings interface*
**Configuration Notes:**
* **API Key**: Must be the key starting with `sk-` obtained from [APIMart Console](https://apimart.ai/keys)
* **Base URL**: Fixed as `https://api.apimart.ai/v1`, note the `/v1` suffix
* **Model ID**: Enter the model ID directly, such as `gpt-5`, `gpt-4o`, `claude-sonnet-4-5-20250929`, etc.
* The configuration interface will display the model's capabilities below (e.g., image support, browser usage)
### 2.4 Save Configuration
After configuration:
1. Click the **Done** button in the top right corner
2. Configuration is saved automatically
3. Cline will immediately connect to APIMart using the new configuration
4. Return to the Cline main interface, showing "What can I do for you?"
## Step 3: Choose the Right Model
### Recommended Models
Choose the appropriate model based on different development scenarios:
**Text Generation & Code Development:**
* **gpt-5** ⭐ Latest model, highest code generation quality
* Suitable for: Complex algorithms, architecture design, code refactoring
* Features: Strong comprehension, high code quality
* **gpt-4o** High-performance model
* Suitable for: Daily development, code review, bug fixing
* Features: Fast, stable quality
* **gpt-4o-mini** 💰 Cost-effective
* Suitable for: Simple code generation, comment writing, documentation
* Features: Great value, quick response
**Claude Series (Strong Reasoning):**
* **claude-sonnet-4-5-20250929**
* Suitable for: Complex logical reasoning, algorithm optimization
* Features: Excellent reasoning, great for complex problems
* **claude-haiku-4-5-20251001**
* Suitable for: Quick code completion, simple Q\&A
* Features: Extremely fast, low cost
**Model Selection Tips:**
* 🚀 **Complex projects, important features:** `gpt-5`, `gpt-4o`, `claude-sonnet-4-5-20250929`
* 💼 **Daily development, routine tasks:** `gpt-4o`, `gpt-4o-mini`
* 💰 **Cost-sensitive, high-frequency use:** `gpt-4o-mini`, `claude-haiku-4-5-20251001`
### Switching Models
At the bottom of the Cline main interface:
1. Find the model button below the input box (shows current model, e.g., `openai-compatible:clau...`)
2. Click this button to switch models
3. Or modify the **Model ID** field in settings
4. Changes take effect immediately, no VSCode restart needed
**Tip:** The current model is shown on the button below the input box; click to quickly switch.
## Step 4: Start Using Cline
### 4.1 Basic Conversation
After configuration, chat with the AI assistant:
1. The Cline main interface will show "**What can I do for you?**"
2. Enter your request in the input box at the bottom (shows "Type your task here...")
3. For example: "Create a function to calculate the Fibonacci sequence"
4. Press `Enter` to send
5. AI will analyze your request, generate code, and can apply it directly to your project
6. Each step's progress is displayed in the sidebar
### 4.2 Code Generation
Let AI generate code:
**Example 1: Create a function**
```
Please create a JavaScript function to validate email address format
```
**Example 2: Implement a feature**
```
Help me implement a user login form with email and password inputs using React Hooks
```
**Example 3: Write tests**
```
Write unit tests for the calculateTotal function using Jest
```
*Chat with AI in Cline to generate code*
### 4.3 Code Explanation and Improvement
Analyze and optimize existing code:
**Right-click menu shortcuts:**
1. Select the code you want to process in the editor
2. Right-click to see Cline options:
* **Explain with Cline** - Explain the code's functionality and logic
* **Improve with Cline** - Optimize and improve the code
3. Select the corresponding action
4. Cline will display analysis results and improvement suggestions in the sidebar
**Through conversation:**
You can also type directly in the Cline sidebar:
```
Refactor this code to improve readability and performance
```
*Right-click to use "Explain with Cline" or "Improve with Cline" for quick code processing*
### 4.4 Bug Debugging
Find and fix errors:
1. Send error messages or problematic code to Cline
2. For example: "This code throws an error: TypeError: Cannot read property 'name' of undefined"
3. AI will analyze the problem and provide solutions
4. You can apply the fix directly
### 4.5 Code Explanation
Understand complex code:
1. Select a difficult-to-understand code snippet
2. Type in Cline: "Explain what this code does"
3. AI will provide a detailed explanation and how it works
### 4.6 Documentation Generation
Automatically generate code documentation:
**Generate function comments:**
```
Add JSDoc comments to this function
```
**Generate README:**
```
Generate a README.md file for this project
```
## Advanced Features
### Multi-file Operations
Cline can handle multiple files simultaneously:
1. **Create multiple files**:
```
Create a complete Express.js API with routes, controllers, and model files
```
2. **Batch modifications**:
```
Replace all var with const or let in the project
```
3. **Project refactoring**:
```
Migrate this project from JavaScript to TypeScript
```
*Cline can create and modify multiple files simultaneously*
### Terminal Command Execution
Cline can help execute terminal commands:
1. **Install dependencies**:
```
Install axios and dotenv packages
```
2. **Run scripts**:
```
Run npm test
```
3. **Git operations**:
```
Create a Git commit with the message "feat: add user authentication"
```
**Command execution flow:**
1. Cline will display "**Cline wants to execute this command:**" in the sidebar
2. Shows the specific command (e.g., `gcc fibonacci.c -o fibonacci.exe`)
3. Two buttons appear at the bottom:
* **Run Command** - Execute the command
* **Reject** - Refuse to execute
4. After clicking "Run Command", the command runs in the integrated terminal
5. Results are displayed in both the terminal and Cline sidebar
**Security Note:** Cline requires your explicit confirmation before executing terminal commands. Please carefully check the command content, especially for sensitive operations involving file deletion or system configuration, before clicking "Run Command".
### Context Management
Cline automatically manages conversation context:
* **Current file context**: Automatically includes the file being edited
* **Selected code context**: Automatically includes code snippets you select
* **Project structure context**: Understands your project structure
* **Error message context**: Automatically captures terminal error messages
### Custom Prompts
Create custom prompt templates:
1. Find **Custom Instructions** in Cline settings
2. Add your preferences, for example:
```
- Use TypeScript instead of JavaScript
- Follow Airbnb code style
- Use arrow function syntax
- Prefer functional programming style
```
3. AI will follow these instructions in all interactions
## FAQ
### Q1: Cline says API key is invalid?
**Solutions:**
1. **Check API Key format**:
* Confirm the API Key starts with `sk-`
* Ensure it's copied completely without extra spaces
2. **Check Base URL**:
* Must be `https://api.apimart.ai/v1`
* Note the `/v1` suffix
3. **Verify key validity**:
* Check key status at [APIMart Console](https://apimart.ai/keys)
* Confirm sufficient account balance
4. **Reconfigure**:
* Delete existing configuration
* Re-enter API Key and Base URL
### Q2: Cline responds slowly?
**Solutions:**
1. **Switch to a faster model**:
* Use `gpt-4o-mini` or `claude-haiku-4-5-20251001`
* These models respond faster
2. **Reduce context length**:
* Avoid sending very long code at once
* Break large tasks into smaller ones
3. **Check network connection**:
* Ensure stable network
* Consider using a proxy server
4. **Optimize request content**:
* Ask more specific questions
* Avoid vague or overly broad questions
### Q3: Cline generates low-quality code?
**Solutions:**
1. **Use higher-quality models**:
* Switch to `gpt-5` or `claude-sonnet-4-5-20250929`
* These models produce higher quality code
2. **Provide more detailed requirements**:
* Clearly state expected implementation
* Provide example code or references
* Specify tech stack and framework versions
3. **Use custom instructions**:
* Add code standards in settings
* Specify coding style and best practices
4. **Iterative optimization**:
* Have multiple conversation rounds with AI
* Gradually improve code quality
### Q4: How to manage API usage costs?
**Solutions:**
1. **Choose appropriate models**:
* Use `gpt-4o-mini` for daily development
* Use `gpt-5` for complex tasks
2. **Optimize question approach**:
* Be as specific as possible
* Avoid repeating the same questions
3. **Use code selection**:
* Only select the code portion that needs processing
* Avoid sending entire file context
4. **Monitor usage**:
* Regularly check the [APIMart Console](https://apimart.ai/overview)
* Understand API call frequency and costs
### Q5: Cline can't access certain files?
**Solutions:**
1. **Check file permissions**:
* Ensure files have read/write permissions
* Especially on Linux/macOS systems
2. **Check .gitignore**:
* Cline ignores files in .gitignore by default
* You can adjust this behavior in settings
3. **Workspace settings**:
* Ensure files are within the VSCode workspace
* Check workspace trust settings
4. **Reload VSCode**:
* Use `Ctrl+Shift+P` / `Cmd+Shift+P`
* Run the "Reload Window" command
## Usage Tips
### 1. Leverage Context Fully
**Provide complete information:**
```
I have an Express.js project using MongoDB database.
Please help me create a user authentication system including registration, login, and JWT token verification.
Project structure is:
- src/models/
- src/controllers/
- src/routes/
- src/middleware/
```
### 2. Incremental Development
**Start simple, gradually refine:**
```
Step 1: Create the basic user model
Step 2: Add password encryption
Step 3: Implement registration and login endpoints
Step 4: Add JWT token verification
```
### 3. Code Review Assistant
**Let AI review your code:**
```
Please review this code, checking for:
1. Potential security issues
2. Performance optimization opportunities
3. Code style issues
4. Possible bugs
```
### 4. Learn New Technologies
**Use Cline to learn:**
```
I want to learn React Hooks.
Please create a sample project demonstrating useState, useEffect, useContext usage,
and add detailed comments explaining how each Hook works.
```
### 5. Rapid Prototyping
**Quickly validate ideas:**
```
Create a simple todo app with requirements:
- Use React and LocalStorage
- Can add, delete, mark as complete
- Simple CSS styling
- Complete in a single HTML file
```
### 6. Pair Programming
**Collaborate with AI:**
```
I'm implementing a sorting algorithm,
I wrote the first half, please help me complete the rest:
function quickSort(arr) {
if (arr.length <= 1) return arr;
const pivot = arr[0];
// Please continue implementation...
}
```
## Feature Highlights
With Cline + APIMart, you can:
* 💻 **Intelligent Code Generation** - Generate high-quality code from natural language descriptions
* 🔧 **Code Refactoring** - Automatically optimize code structure and performance
* 🐛 **Bug Debugging Assistance** - Quickly locate and fix code issues
* 📝 **Documentation Generation** - Generate comments, README, API documentation
* 🧪 **Test Case Writing** - Automatically generate unit and integration tests
* 🔄 **Code Migration** - Language conversion, framework migration
* 💡 **Code Explanation** - Understand complex code logic
* 🎯 **Best Practice Suggestions** - Provide code standards and optimization advice
* 🚀 **Rapid Prototyping** - Quickly validate ideas and concepts
* 🤖 **Terminal Command Execution** - Automatically execute development commands
## Keyboard Shortcuts
Common Cline shortcuts:
| Shortcut | Function | Description |
| ------------------------------ | --------------------- | ----------------------------- |
| `Ctrl+Shift+P` / `Cmd+Shift+P` | Command Palette | Access all Cline commands |
| `Ctrl+Shift+X` / `Cmd+Shift+X` | Extension Marketplace | Install and manage extensions |
| Click Cline icon | Open/Close sidebar | Quick access to Cline |
| `Ctrl+K Ctrl+I` | Inline suggestions | Get AI suggestions in editor |
**Tip:** You can customize Cline's shortcuts in VSCode's keyboard shortcuts settings.
## Best Practices
### 1. Clear Task Description
❌ **Poor question:**
```
Write a login feature
```
✅ **Good question:**
```
Create a user login feature with requirements:
- Use React and TypeScript
- Form validation (email format, password length)
- Use axios to call API
- Store JWT token to localStorage on successful login
- Error handling and user feedback
```
### 2. Provide Context Information
**Include project-related information:**
* Tech stack and frameworks used
* Relevant file structure
* Existing code conventions
* Third-party library dependencies
### 3. Iterative Improvement
**Don't expect perfection the first time:**
1. Generate basic functionality first
2. Test and validate
3. Provide improvement feedback
4. Gradually refine
### 4. Code Review
**Always review generated code:**
* Check logical correctness
* Verify security
* Test edge cases
* Ensure compliance with project standards
### 5. Maintain Conversation Continuity
**Leverage context continuity:**
```
Round 1: Create user model
Round 2: Based on the model just created, create CRUD endpoints
Round 3: Add permission validation to these endpoints
```
## Support & Help
If you encounter any issues:
* 📚 [APIMart Documentation](https://docs.apimart.ai)
* 📚 [Cline Official Documentation](https://github.com/clinebot/cline)
* 💬 [Discord Community](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 Technical Support: [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
## Video Tutorials
**Coming Soon:** We are creating detailed video tutorials covering various use cases and best practices for Cline + APIMart.
***
Register for APIMart now, get your API key, and experience AI-assisted development in VSCode!
# Using APIMart in Codex CLI
Source: https://docs.apimart.ai/en/integrations/dev-tool/codex-cli
A detailed guide on configuring and using APIMart API services in Codex CLI, enabling you to access multiple AI models for assisted programming with simple configuration.
## Introduction
Codex CLI is OpenAI's open-source terminal coding agent that can read and write files, run commands, fix bugs, and complete full coding tasks directly in the command line.
By connecting through APIMart, you can freely use multiple models — including GPT and Claude — in Codex CLI, with more flexible and competitive pricing.
## Prerequisites
Before you begin, make sure you have:
1. **Installed Node.js**
Download and install from the [Node.js website](https://nodejs.org/) (latest LTS, v20 or newer recommended) to install Codex CLI via npm
2. **Obtained an APIMart API Key**
Log in to the [APIMart Console](https://apimart.ai/keys) to get your API key (starts with `sk-`)
**Tip:** If you don't have an APIMart account yet, please register at [APIMart](https://apimart.ai) first and obtain your API key.
## Step 1: Install Codex CLI
Choose any of the following methods to install:
Install globally with npm — works on all operating systems:
```bash theme={null}
npm install -g @openai/codex
```
If you run into permission issues, prepend `sudo` (macOS / Linux).
macOS users can also install with Homebrew:
```bash theme={null}
brew install codex
```
### Verify the installation
After installing, run the following command to confirm:
```bash theme={null}
codex --version
```
If a version number is printed, the installation succeeded.
## Step 2: Configure the APIMart API
Codex CLI manages model providers via configuration files under the `~/.codex/` directory. All we need to do is add a custom provider pointing to APIMart.
### 2.1 Locate the config directory
* **macOS / Linux:** `~/.codex/`
* **Windows:** `C:\Users\\.codex\`
If the directory does not exist, run `codex` once in your terminal then press `Ctrl + C` to exit — it will be created automatically.
### 2.2 Configure the API key
In the config directory, create or edit the `auth.json` file and fill in your APIMart key:
```json theme={null}
{
"OPENAI_API_KEY": "sk-xxxxxxxxxxxx"
}
```
| Field | Description |
| ---------------- | ---------------------------------------- |
| `OPENAI_API_KEY` | Your APIMart API key (starts with `sk-`) |
### 2.3 Configure the model provider
In the config directory, create or edit the `config.toml` file and add the APIMart provider:
```toml theme={null}
# Default model
model = "gpt-5.5"
# Default provider — matches [model_providers.apimart] below
model_provider = "apimart"
# APIMart provider configuration
[model_providers.apimart]
name = "APIMart"
base_url = "https://api.apimart.ai/v1"
wire_api = "responses"
requires_openai_auth = true
```
| Field | Description |
| ---------------------- | ------------------------------------------------------------------------- |
| `model` | Default model ID — pick one from the model list below |
| `model_provider` | Default provider — must match the ID inside `[model_providers.xxx]` |
| `name` | Display name of the provider — can be customized |
| `base_url` | APIMart's OpenAI-compatible URL — fixed at `https://api.apimart.ai/v1` |
| `wire_api` | Wire protocol — recent Codex versions require `responses` (Responses API) |
| `requires_openai_auth` | Set to `true` to authenticate using the key from `auth.json` |
After saving both files, restart Codex CLI for the changes to take effect.
Make sure `auth.json` is valid JSON and `config.toml` is valid TOML. Do not use full-width / smart quotes, otherwise the config won't apply.
## Step 3: Get Started
### Verify the configuration
In any project directory, run the following command to confirm everything is wired up:
```bash theme={null}
codex "Introduce yourself in one sentence"
```
If you get an AI reply, the configuration is working. If you see a sign-in screen, or `401` / `403` errors, refer to the FAQ section below.
### Interactive mode
Run `codex` directly to enter the interactive UI — ideal for full coding tasks:
```bash theme={null}
codex
```
Once inside, describe what you need in natural language, e.g.:
```
Create an Express.js server with a JSON-returning health check endpoint
```
Codex will analyze your project, generate code, run commands, and ask for confirmation before performing sensitive operations.
### Approval modes
On first run, Codex will ask you to pick an approval level:
| Mode | Description |
| --------------- | -------------------------------------------------------------------------------- |
| **Read Only** | Only file reads are allowed — any modification or command requires confirmation |
| **Auto** | Can read/write files and run commands within the working directory (recommended) |
| **Full Access** | Performs any operation without confirmation — use with caution |
We recommend starting with **Auto** mode. Type `/approvals` in the interactive UI to change it anytime.
### Switch models
In the interactive UI, type `/model` to switch quickly, or change the `model` field in `config.toml` and restart.
## Supported Models
For Codex CLI, the following GPT-5 series models are recommended:
| Model ID | Strengths | Recommended Use Cases |
| --------------- | ------------------------------------------ | ----------------------------------------- |
| `gpt-5.5` | Latest flagship, top coding ability | First pick for Codex, complex engineering |
| `gpt-5.4` | Previous-generation flagship, very capable | Complex coding, architecture design |
| `gpt-5.4-mini` | Lightweight, fast, cost-effective | Daily coding, fast iteration |
| `gpt-5.3-codex` | Coding model optimized for Codex | Agentic coding tasks |
| `gpt-5.2` | Stable and balanced | Routine coding tasks |
**Model selection tips:** The GPT-5 series above pairs best with Codex CLI. For the best experience, prefer `gpt-5.5`; `gpt-5.3-codex` is specifically optimized for Codex's agentic coding scenarios.
## Common Commands
Frequently used commands and shortcuts in Codex CLI:
| Command | Description |
| ----------------------- | -------------------------------------- |
| `codex` | Enter the interactive UI |
| `codex "task"` | Start with an initial instruction |
| `codex exec "task"` | Non-interactive mode — run and exit |
| `codex --model gpt-5.4` | Start with a specified model |
| `codex --version` | Show the version number |
| `/model` | Switch model inside the interactive UI |
| `/approvals` | Adjust approval mode inside the UI |
| `Ctrl + C` | Exit the interactive UI |
## FAQ
### Q1: A ChatGPT sign-in screen appears after launch?
If you see "Sign in with ChatGPT" or similar after launch, the configuration didn't take effect.
**Troubleshooting:**
1. Make sure both `config.toml` and `auth.json` are inside `~/.codex/`
2. Check that `model_provider` in `config.toml` is set to `apimart`
3. Check that `auth.json` is valid JSON and the key is filled in completely
### Q2: Getting 401 / 403 errors?
| Status Code | Meaning | Solution |
| ------------------ | -------------------------------------- | -------------------------------------------------------------- |
| `401 Unauthorized` | Missing or invalid API key | Check the key in `auth.json` — it should start with `sk-` |
| `403 Forbidden` | Insufficient permission or expired key | Go to the [Console](https://apimart.ai/keys) to verify the key |
Also make sure `base_url` is set to `https://api.apimart.ai/v1`, not the official OpenAI URL.
### Q3: Connection failed?
1. Check your network connection
2. Make sure `base_url` in `config.toml` is correct
3. If you're behind a proxy, ensure it allows access to `api.apimart.ai`
### Q4: `wire_api = "chat"` is no longer supported?
Recent Codex CLI versions (0.84.0 and later) have removed the `chat` protocol. Update `wire_api` in `config.toml` to `responses`:
```toml theme={null}
wire_api = "responses"
```
APIMart supports the Responses API — just restart Codex after the change.
### Q5: Tool calls or runs are failing?
Make sure `wire_api` in `config.toml` is set to `responses`. If you still hit compatibility issues, switch to a recommended GPT-5 series model (e.g. `gpt-5.5`, `gpt-5.3-codex`) — they pair more reliably with Codex CLI.
### Q6: Use environment variables instead of auth.json?
You can also configure the key via an environment variable. Change the provider block in `config.toml` to:
```toml theme={null}
[model_providers.apimart]
name = "APIMart"
base_url = "https://api.apimart.ai/v1"
wire_api = "responses"
env_key = "APIMART_API_KEY"
```
Then set the environment variable `APIMART_API_KEY` to your APIMart key. `auth.json` is no longer required in this setup.
### Q7: How do I switch models?
Two ways:
1. **In the interactive UI**: Type `/model` to switch
2. **Edit the config**: Change the `model` field in `config.toml` and restart Codex CLI
### Q8: How do I check usage and billing?
Log in to the [APIMart Console](https://apimart.ai/overview) to view API call statistics, token consumption details, and cost trends.
## Support and Help
If you run into any issues while using Codex CLI:
* 📚 [APIMart Documentation Center](https://docs.apimart.ai)
* 💬 [Discord Community](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 Technical support: [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
***
Sign up for APIMart now, get your API key, and experience a multi-model programming assistant in Codex CLI!
# Using APIMart in Cursor
Source: https://docs.apimart.ai/en/integrations/dev-tool/cursor
Detailed guide on how to configure and use APIMart API service in Cursor AI code editor. This guide will help you configure APIMart API in Cursor to access rich AI model resources for code development.
## Prerequisites
Before you begin, please ensure:
1. **Cursor is installed**\
Download and install the version suitable for your OS from the [Cursor website](https://cursor.sh/)
2. **You have an APIMart API key**\
Log in to the [APIMart Console](https://apimart.ai/keys) to get your API key (starts with `sk-`)
**Tip:** If you don’t have an APIMart account yet, register at [APIMart](https://apimart.ai) and obtain an API key first.
## Step 1: Open Cursor Settings
After launching Cursor, open Settings:
1. Click the **⚙️ Settings** icon (gear) in the top-right corner
2. Or use shortcuts:
* Windows/Linux: `Ctrl+Shift+J`
* macOS: `Cmd+Shift+J`
*Cursor main interface — open Settings from the top-right gear*
## Step 2: Configure model settings
### 2.1 Open model settings
In Settings:
1. Find **Models** in the left sidebar
2. Open the model settings page
*Find “Models” in the left sidebar*
### 2.2 Use OpenAI API Key
On the model settings page:
1. Find the **OpenAI API Key** section
2. Click **Add new** or **Override OpenAI Base URL**
**Important:** Cursor supports OpenAI-compatible APIs, so APIMart can be configured as a custom provider.
### 2.3 Configure APIMart
Enter the following:
| Setting | Value |
| ------------ | ---------------------------------------- |
| **API Key** | Your APIMart API key (`sk-xxxxxxxxxxxx`) |
| **Base URL** | `https://api.apimart.ai/v1` |
**Important:** - Base URL must include the `/v1` suffix: `https://api.apimart.ai/v1` - The API key must be the `sk-...` key from the APIMart console - After saving, Cursor uses APIMart models for completion and chat
*Enter API Key and Base URL*
## Step 3: Choose models
### 3.1 Model selection
In model settings you can choose which models to use.
**Available families:**
* **GPT-4/5** — strong for complex code generation and Q\&A
* `gpt-5` — latest GPT-5
* `gpt-4o` — GPT-4o
* `gpt-4o-mini` — faster, lower cost
* **Claude** — strong for understanding and refactoring
* `claude-sonnet-4-5-20250929` — Claude Sonnet 4.5
* `claude-haiku-4-5-20251001` — Claude Haiku 4.5
* **Other**
* `gemini-2.0-flash-exp` — Google Gemini 2.0 Flash
**Suggestions:** - 💰 **Completion (cost-efficient):** `gpt-4o-mini` - 🚀 **Hard tasks (performance):** `gpt-5`, `gpt-4o`, `claude-sonnet-4-5-20250929` - ⚡ **Low latency:** `gpt-4o-mini`, `gemini-2.0-flash-exp`
### 3.2 Per-feature models
You can pick different models per feature:
* **Chat** — conversations with the AI
* **Autocomplete** — inline suggestions
* **Cmd+K** — quick edit / generate
Choose the best fit for each workflow.
## Step 4: Start using
Once configured, you can use Cursor’s AI features.
### 4.1 AI Chat (`Cmd+L` / `Ctrl+L`)
1. Press `Cmd+L` (macOS) or `Ctrl+L` (Windows/Linux)
2. Ask a question or give a task, for example:
* “How do I implement quicksort?”
* “Help me optimize this code’s performance”
* “Explain how this function works”
*Chat with the assistant*
### 4.2 Code completion
1. Type as usual in the editor
2. Cursor suggests completions
3. Press `Tab` to accept
*Inline completion example*
### 4.3 Quick edit (`Cmd+K` / `Ctrl+K`)
1. Select code
2. Press `Cmd+K` (macOS) or `Ctrl+K` (Windows/Linux)
3. Describe the edit, e.g.:
* “Add error handling”
* “Refactor this function”
* “Add type annotations”
*Quick edit with Cmd+K*
### 4.4 Explain code
1. Select the code
2. Right-click **Explain with AI** (or shortcut)
3. The AI explains behavior and logic
## FAQ
### Q1: Can’t reach APIMart?
**Try:**
1. **Base URL** — must be exactly `https://api.apimart.ai/v1`
2. **API key** — valid `sk-...` key from the [console](https://apimart.ai/keys)
3. **Network** — ensure `https://api.apimart.ai` is reachable; a proxy may be required in some regions
### Q2: Slow responses?
**Try:**
1. Use a lighter model (`gpt-4o-mini` instead of `gpt-4o`, or `gemini-2.0-flash-exp`)
2. Shorten context — send less code, ask more precise questions
3. Check latency / proxy if needed
### Q3: API errors?
| Message | Likely cause | What to do |
| --------------------------- | ---------------------- | ------------------------------- |
| `401 Unauthorized` | Bad or expired key | Re-create key and update Cursor |
| `429 Too Many Requests` | Rate limited | Wait and retry |
| `500 Internal Server Error` | Temporary server issue | Retry later |
| `insufficient_quota` | Low balance | Top up in console |
### Q4: Usage and billing?
Open the [APIMart Console](https://apimart.ai/overview):
* 📊 Call statistics
* 💰 Cost breakdown
* 📈 Usage trends
* 🔍 Request logs
## Tips
### 1. Use context
* Open related files
* Reference files with `@filename`
* Reference folders with `@folder`
### 2. Clear prompts
**❌ Weak:**
```
optimize this
```
**✅ Strong:**
```
Optimize this function for performance:
1. Reduce nested loops
2. Prefer more efficient data structures
3. Add caching where helpful
```
### 3. Iterate
Start small → refine → test → adjust prompts.
### 4. Project rules
Define style, naming, architecture, and tests in `.cursorrules`.
## Features
With Cursor + APIMart:
* 💬 Chat for coding questions
* ⚡ Smart completion
* ✏️ Natural-language edits
* 🔍 Deeper code understanding
* 🐛 Debugging help
* 📝 Docs and comments
* 🔄 Refactoring
* 🧪 Test scaffolding
## Support
* 📚 [APIMart Documentation](https://docs.apimart.ai)
* 💬 [Discord](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
***
Sign up, get your API key, and ship faster with Cursor!
# Using APIMart with Gemini CLI
Source: https://docs.apimart.ai/en/integrations/dev-tool/gemini
Detailed guide on configuring APIMart API service in Gemini CLI command-line tool. Learn how to use APIMart’s AI models—including Gemini, GPT, and Claude series—from the terminal.
## Introduction
Gemini CLI is Google’s official command-line tool that lets developers interact with Gemini AI models from the terminal. After configuring APIMart API, you can use APIMart’s advanced models—GPT, Claude, and Gemini—in Gemini CLI.
## Prerequisites
Before you start:
1. **Node.js and npm installed**\
Download and install from the [Node.js website](https://nodejs.org/) (v16 or higher recommended)
2. **APIMart API key**\
Sign in to the [APIMart Console](https://apimart.ai/keys) and copy your API key (starts with `sk-`)
**Tip:** If you don’t have an APIMart account yet, register at [APIMart](https://apimart.ai) first and create an API key.
## Step 1: Install Gemini CLI
### 1.1 Global install
Install Gemini CLI globally with npm:
```bash theme={null}
npm install -g @google/gemini-cli
```
### 1.2 Verify installation
Check that the CLI is available:
```bash theme={null}
gemini --version
```
If a version number is printed, installation succeeded.
**Tip:** If the command is not found, restart your terminal or check your npm global `PATH` configuration.
## Step 2: Configure APIMart API
### 2.1 Temporary environment variables
For testing or one-off use; values are cleared when you close the terminal.
**Windows (PowerShell):**
```powershell theme={null}
$env:GEMINI_API_KEY = "sk-xxxxxxxxxxxx"
$env:GEMINI_BASE_URL = "https://api.apimart.ai/v1"
```
**macOS/Linux (Bash):**
```bash theme={null}
export GEMINI_API_KEY="sk-xxxxxxxxxxxx"
export GEMINI_BASE_URL="https://api.apimart.ai/v1"
```
### 2.2 Permanent environment variables (recommended)
Persist configuration so new shells pick it up automatically.
**Windows (PowerShell):**
1. Run PowerShell as Administrator
2. Set user-level environment variables:
```powershell theme={null}
[System.Environment]::SetEnvironmentVariable('GEMINI_API_KEY', 'sk-xxxxxxxxxxxx', 'User')
[System.Environment]::SetEnvironmentVariable('GEMINI_BASE_URL', 'https://api.apimart.ai/v1', 'User')
```
3. Restart PowerShell, or reload variables:
```powershell theme={null}
$env:GEMINI_API_KEY = [System.Environment]::GetEnvironmentVariable('GEMINI_API_KEY', 'User')
$env:GEMINI_BASE_URL = [System.Environment]::GetEnvironmentVariable('GEMINI_BASE_URL', 'User')
```
**macOS/Linux (Bash):**
1. Edit your shell rc file:
```bash theme={null}
# Bash
nano ~/.bashrc
# Zsh (default on macOS)
nano ~/.zshrc
```
2. Append:
```bash theme={null}
# APIMart Gemini CLI
export GEMINI_API_KEY="sk-xxxxxxxxxxxx"
export GEMINI_BASE_URL="https://api.apimart.ai/v1"
```
3. Reload:
```bash theme={null}
source ~/.bashrc # Bash
source ~/.zshrc # Zsh
```
### 2.3 Using a `.env` file
Create `.env` in your project:
```bash theme={null}
# .env
GEMINI_API_KEY=sk-xxxxxxxxxxxx
GEMINI_BASE_URL=https://api.apimart.ai/v1
```
Load variables before running Gemini:
**macOS/Linux:**
```bash theme={null}
export $(cat .env | xargs) && gemini chat
```
**Windows (PowerShell):**
```powershell theme={null}
Get-Content .env | ForEach-Object {
$name, $value = $_.split('=')
Set-Content env:\$name $value
}
gemini chat
```
**Important:** - Replace `sk-xxxxxxxxxxxx` with your real key from the [APIMart Console](https://apimart.ai/keys) - Set `GEMINI_BASE_URL` to `https://api.apimart.ai/v1` so Gemini CLI talks to APIMart - Add `.env` to `.gitignore` so keys are not committed
### 2.4 Verify configuration
**macOS/Linux:**
```bash theme={null}
echo $GEMINI_API_KEY
echo $GEMINI_BASE_URL
```
**Windows (PowerShell):**
```powershell theme={null}
echo $env:GEMINI_API_KEY
echo $env:GEMINI_BASE_URL
```
If the values look correct, configuration succeeded.
## Step 3: Use Gemini CLI
### 3.1 Basic chat
Interactive session:
```bash theme={null}
gemini chat
```
One-off prompt:
```bash theme={null}
gemini "Give a short overview of the history of artificial intelligence"
```
### 3.2 Choose a model
```bash theme={null}
gemini chat --model gpt-4o
```
Or:
```bash theme={null}
gemini "Write a Python quicksort implementation" --model claude-sonnet-4-5-20250929
```
### 3.3 Read prompts from a file
```bash theme={null}
gemini --input prompt.txt
```
Or pipe:
```bash theme={null}
cat prompt.txt | gemini
```
### 3.4 Save output to a file
```bash theme={null}
gemini "Generate a React component" --output component.jsx
```
## Step 4: Call APIMart from your code
### 4.1 Python SDK
```python theme={null}
import openai
# APIMart
openai.api_key = "sk-xxxxxxxxxxxx" # Your APIMart API key
openai.api_base = "https://api.apimart.ai/v1"
response = openai.ChatCompletion.create(
model="gemini-2.0-flash-exp",
messages=[
{"role": "user", "content": "Hi—please introduce yourself"}
]
)
print(response.choices[0].message.content)
```
### 4.2 JavaScript / TypeScript
```javascript theme={null}
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "sk-xxxxxxxxxxxx",
baseURL: "https://api.apimart.ai/v1",
});
async function main() {
const completion = await client.chat.completions.create({
model: "gemini-2.0-flash-exp",
messages: [{ role: "user", content: "Hi—please introduce yourself" }],
});
console.log(completion.choices[0].message.content);
}
main();
```
### 4.3 cURL
```bash theme={null}
curl https://api.apimart.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-xxxxxxxxxxxx" \
-d '{
"model": "gemini-2.0-flash-exp",
"messages": [
{"role": "user", "content": "Hi—please introduce yourself"}
]
}'
```
## Step 5: Pick a model
### Recommended models
APIMart supports many models; choose by task and budget.
**Gemini**
| Model name | Model ID | Characteristics | Good for |
| ---------------- | ---------------------- | ----------------- | ---------------------------- |
| Gemini 2.0 Flash | `gemini-2.0-flash-exp` | Fast, multimodal | Quick answers, vision + text |
| Gemini 2.5 Pro | `gemini-2.5-pro` | Strong capability | Hard problems, analysis |
| Gemini 2.5 Flash | `gemini-2.5-flash` | Very responsive | Real-time chat, batch jobs |
**GPT**
| Model name | Model ID | Characteristics | Good for |
| ----------- | ------------- | --------------- | --------------------------- |
| GPT-5 | `gpt-5` | Top-tier | Reasoning, creative writing |
| GPT-4o | `gpt-4o` | High quality | General chat, content |
| GPT-4o Mini | `gpt-4o-mini` | Cost-efficient | Simple tasks, high volume |
**Claude**
| Model name | Model ID | Characteristics | Good for |
| ----------------- | ---------------------------- | ---------------- | ---------------------- |
| Claude Sonnet 4.5 | `claude-sonnet-4-5-20250929` | Strong reasoning | Code, logic |
| Claude Haiku 4.5 | `claude-haiku-4-5-20251001` | Very fast | Q\&A, low-latency chat |
**Quick picks:** - 🚀 **Google-style stack:** `gemini-2.0-flash-exp`, `gemini-2.5-pro` - 💡 **Coding:** `claude-sonnet-4-5-20250929`, `gpt-5` - 💰 **Cost:** `gpt-4o-mini`, `claude-haiku-4-5-20251001` - ⚡ **Speed:** `gemini-2.0-flash-exp`, `gpt-4o-mini`
## Advanced features
### Multimodal (images)
With a multimodal model such as Gemini 2.0 Flash:
```python theme={null}
response = openai.ChatCompletion.create(
model="gemini-2.0-flash-exp",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "What’s in this image?"},
{
"type": "image_url",
"image_url": {
"url": "https://example.com/image.jpg"
}
}
]
}
]
)
```
### Streaming
Stream tokens as they arrive:
```python theme={null}
stream = openai.ChatCompletion.create(
model="gemini-2.0-flash-exp",
messages=[{"role": "user", "content": "Write a short poem about spring"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end='')
```
### Tuning parameters
Shape randomness and length:
```python theme={null}
response = openai.ChatCompletion.create(
model="gemini-2.0-flash-exp",
messages=[{"role": "user", "content": "Your question"}],
temperature=0.7, # randomness (0–2)
max_tokens=2000, # max output length
top_p=0.9, # nucleus sampling
presence_penalty=0, # topic diversity
frequency_penalty=0 # repetition penalty
)
```
## FAQ
### Q1: “Invalid API key” or auth errors
1. **Key format**
* Must start with `sk-`
* No extra spaces when pasting
2. **Environment variables**
```bash theme={null}
# macOS / Linux
echo $GEMINI_API_KEY
echo $GEMINI_BASE_URL
# Windows PowerShell
echo $env:GEMINI_API_KEY
echo $env:GEMINI_BASE_URL
```
3. **Key status**
* Check the key in the [APIMart Console](https://apimart.ai/keys)
* Ensure your account has balance
### Q2: How do I verify the API setup?
```python theme={null}
import openai
openai.api_key = "sk-xxxxxxxxxxxx"
openai.api_base = "https://api.apimart.ai/v1"
try:
response = openai.ChatCompletion.create(
model="gemini-2.0-flash-exp",
messages=[{"role": "user", "content": "test"}],
max_tokens=10
)
print("✅ API configuration OK")
print(f"Reply: {response.choices[0].message.content}")
except Exception as e:
print(f"❌ API configuration failed: {e}")
```
### Q3: Which languages are supported?
Any language that can send HTTP requests works with APIMart:
* ✅ **Python** — OpenAI SDK recommended
* ✅ **JavaScript / TypeScript** — Node or browser
* ✅ **Java** — HTTP client
* ✅ **Go** — stdlib or libraries
* ✅ **PHP** — cURL or Guzzle
* ✅ **Ruby** — HTTP gems
* ✅ **C# / .NET** — `HttpClient`
* ✅ **Swift** — `URLSession`
* ✅ **Others** — anything with HTTP
### Q4: Where can I see usage and billing?
In the [APIMart Console](https://apimart.ai/overview):
* 📊 Live call stats
* 💰 Cost and invoices
* 📈 Usage trends
* 🔍 Request logs
* ⚙️ API key management
### Q5: Common API errors
| Error | Likely cause | What to do |
| --------------------------- | ---------------------- | ------------------------------------------- |
| `401 Unauthorized` | Bad or revoked key | Fix key in env / console |
| `429 Too Many Requests` | Rate limit | Slow down or upgrade plan |
| `500 Internal Server Error` | Transient server issue | Retry later; contact support if it persists |
| `insufficient_quota` | Low balance | Top up in console |
## Best practices
### 1. Retries and backoff
```python theme={null}
import openai
import time
def call_with_retry(max_retries=3):
for i in range(max_retries):
try:
response = openai.ChatCompletion.create(
model="gemini-2.0-flash-exp",
messages=[{"role": "user", "content": "Your question"}]
)
return response
except openai.error.RateLimitError:
if i < max_retries - 1:
time.sleep(2 ** i)
continue
raise
except Exception as e:
print(f"Error: {e}")
raise
response = call_with_retry()
```
### 2. Cost control
```python theme={null}
def choose_model(complexity):
if complexity == "simple":
return "gpt-4o-mini"
elif complexity == "medium":
return "gemini-2.0-flash-exp"
return "gpt-5"
model = choose_model("simple")
response = openai.ChatCompletion.create(
model=model,
messages=[{"role": "user", "content": "Your question"}],
max_tokens=500
)
```
### 3. System prompts
```python theme={null}
response = openai.ChatCompletion.create(
model="gemini-2.0-flash-exp",
messages=[
{
"role": "system",
"content": "You are an expert Python assistant who writes clear, efficient code."
},
{
"role": "user",
"content": "Implement quicksort for me"
}
]
)
```
## Features
With **Google AI Studio** and **APIMart** you get:
* 🤖 **Many models** — GPT, Claude, Gemini, and more
* 🌍 **OpenAI-compatible** — familiar request / response shape
* ⚡ **Performance** — low latency, high concurrency
* 💰 **Clear pricing** — pay as you go
* 📊 **Observability** — monitor calls in real time
* 🔒 **Security** — enterprise-oriented safeguards
* 🚀 **Fast integration** — simple HTTP / SDK calls
* 📚 **Docs** — guides and examples
## Support
* 📚 [APIMart documentation](https://docs.apimart.ai)
* 📚 [Google AI Studio documentation](https://ai.google.dev/docs)
* 💬 [Discord](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
***
Create an account, grab an API key, and use multiple AI models from Google AI Studio workflows and beyond.
# Using APIMart in Dify
Source: https://docs.apimart.ai/en/integrations/platform/dify
Detailed guide on how to configure and use APIMart API service in Dify LLMOps platform. This guide will help you configure APIMart API in Dify to build powerful AI applications.
## Prerequisites
Before you begin, please ensure:
1. **Dify account registered**
Visit [Dify Official Website](https://dify.ai/) to register an account, choose cloud or self-hosted version
2. **APIMart API Key obtained**
Log in to [APIMart Console](https://apimart.ai/keys) to get your API key (starts with `sk-`)
**Tip:** If you don't have an APIMart account yet, please register at [APIMart](https://apimart.ai) and obtain an API key first.
## Step 1: Log in to Dify and Access Settings
### 1.1 Access Dify Platform
* **Cloud Version:** Visit [https://cloud.dify.ai](https://cloud.dify.ai) and log in
* **Self-hosted Version:** Visit your Dify deployment address
*Dify main interface showing application list and create app button*
### 1.2 Navigate to Model Settings
1. Click the **avatar icon** in the top right corner
2. Select **Settings**
3. Choose **Model Provider** in the left menu
*Find "Model Provider" option in the left menu*
**Note:** Dify supports configuring multiple model providers. You can use APIMart alongside other providers.
## Step 2: Add APIMart Model Provider
**Configuration Methods:** There are two ways to configure APIMart in Dify:
**Method 1 (Recommended):** Use OpenAI Provider's Custom API Feature
* In OpenAI provider settings, directly modify Base URL to `https://api.apimart.ai/v1`
* Enter your APIMart API Key
* Faster and simpler configuration
**Method 2:** Add as Custom Model Provider (This Guide's Method)
* More flexible, can manage APIMart provider separately
* Convenient for using multiple API providers simultaneously
Both methods are functionally identical. Choose based on your preference.
### 2.1 Select Configuration Method
#### Method 1: Use OpenAI Custom API (Recommended)
1. Find the **OpenAI** provider on the Model Provider page
2. Click the **Configure** or **Settings** button
3. On the configuration page:
* **API Key**: Enter your APIMart API key (`sk-xxxxxxxxxxxx`)
* **API Base URL** or **Base URL**: Enter `https://api.apimart.ai/v1`
4. Click **Save**
*Configure APIMart's API Key and Base URL in OpenAI provider*
5. After configuration, return to the OpenAI provider page and view the **Model List**
6. In the model list, find the models you need (e.g., `gpt-4o`, `gpt-4o-mini`, `chatgpt-4o-latest`, etc.)
7. Click the **switch** on the right side of the model to enable it (blue indicates enabled)
*Enable the models you need in the OpenAI model list*
**Important:** Only enable models that are actually supported by APIMart!
Although Dify's OpenAI model list displays many models, only those supported by APIMart will work correctly. Enabling unsupported models will cause API call failures.
Please refer to [APIMart API Documentation](https://docs.apimart.ai) for the complete list of supported models.
**APIMart supported and recommended models:**
**GPT Series:**
* `gpt-5` / `gpt-5-chat-latest` - GPT-5 series models
* `chatgpt-4o-latest` / `gpt-4o` - Latest GPT-4o model
* `gpt-4o-mini` - Fast and economical version
* `gpt-4.1` / `gpt-4.1-mini` - GPT-4.1 series
**Claude Series:**
* `claude-sonnet-4-5-20250929` - Claude Sonnet 4.5
* `claude-haiku-4-5-20251001` - Claude Haiku 4.5
**Gemini Series:**
* `gemini-2.0-flash-exp` - Google Gemini 2.0 Flash
You can enable multiple models simultaneously and switch between them flexibly in your applications.
After completion, you can use it directly. Jump to **Step 3**.
#### Method 2: Add Custom Model Provider
On the Model Provider page:
1. Scroll down to the **Custom Model** section
2. Click the **+ Add Model** button
*Scroll to the custom model section and click "+ Add Model" button*
### 2.2 Configure APIMart Provider
In the configuration dialog, fill in the following information:
| Field | Value |
| ----------------------- | --------------------------------------------------------------------------------------------- |
| **Model Name** | `APIMart` or custom name |
| **Model Type** | Select `LLM` (Large Language Model) |
| **API Key** | Your APIMart API key (`sk-xxxxxxxxxxxx`) |
| **API endpoint URL** | `https://api.apimart.ai/v1` |
| **Endpoint model name** | Enter specific model name (e.g., `gpt-4o`, `gpt-4o-mini`, `claude-sonnet-4-5-20250929`, etc.) |
*Fill in APIMart provider configuration*
**Important:**
* Base URL must include `/v1` suffix: `https://api.apimart.ai/v1`
* API Key must be obtained from APIMart console and start with `sk-`
* Ensure your API key has sufficient balance
### 2.3 Add More Models (Optional)
To add more models, repeat the above steps:
1. In the custom model section, click the **+ Add Model** button again
2. Fill in the configuration information for another model
3. Click Save
*Repeat the add model steps to configure multiple different models*
**Recommended Models to Add:**
#### GPT-4/5 Series
| Model ID | Model Name | Context Length | Use Case |
| ------------- | ----------- | -------------- | ----------------------------------- |
| `gpt-5` | GPT-5 | 128,000 | Complex tasks, long text processing |
| `gpt-4o` | GPT-4o | 128,000 | High-quality chat, code generation |
| `gpt-4o-mini` | GPT-4o Mini | 128,000 | Fast response, cost-effective |
#### Claude Series
| Model ID | Model Name | Context Length | Use Case |
| ---------------------------- | ----------------- | -------------- | -------------------------------- |
| `claude-sonnet-4-5-20250929` | Claude Sonnet 4.5 | 200,000 | Complex reasoning, code analysis |
| `claude-haiku-4-5-20251001` | Claude Haiku 4.5 | 200,000 | Fast response, simple tasks |
#### Gemini Series
| Model ID | Model Name | Context Length | Use Case |
| ---------------------- | ---------------- | -------------- | ---------------------------------- |
| `gemini-2.0-flash-exp` | Gemini 2.0 Flash | 32,000 | Multimodal, real-time applications |
**Performance Recommendations:**
* 💰 **Cost-effective:** `gpt-4o-mini`, `claude-haiku-4-5-20251001`
* 🚀 **High-performance:** `gpt-5`, `gpt-4o`, `claude-sonnet-4-5-20250929`
* ⚡ **Fast response:** `gemini-2.0-flash-exp`, `gpt-4o-mini`
## Step 3: Use APIMart Models in Applications
### 3.1 Create New Application
1. Return to Dify homepage
2. Click **Create App** button
3. Select application type:
* **Chatbot** - Conversational application
* **Text Generator** - Text generation application
* **Agent** - Intelligent agent
* **Workflow** - Complex workflow application
*Select application type to create new app*
### 3.2 Select APIMart Model
On the application orchestration page:
1. Find the **Model Settings** area
2. Click the **Select Model** dropdown
3. Select **APIMart** provider
4. Choose your configured model (e.g., `gpt-4o`)
*Select APIMart provider's model in the application*
### 3.3 Configure Model Parameters
Adjust model parameters as needed:
| Parameter | Description | Recommended Value |
| --------------------- | -------------------------- | ------------------------------ |
| **Temperature** | Controls output randomness | 0.7 (creative) / 0.3 (precise) |
| **Max Tokens** | Maximum output length | 2000-4000 |
| **Top P** | Nucleus sampling parameter | 0.9 |
| **Presence Penalty** | Reduce repetition | 0.0-0.5 |
| **Frequency Penalty** | Reduce frequent words | 0.0-0.5 |
*Adjust model parameters based on application needs*
## Step 4: Build and Test Application
### 4.1 Add Prompts
On the application orchestration page:
1. Write prompts in the **System Prompt** area
2. Use variables to make your app dynamic:
* `{{variable_name}}` - User input variable
* `{{context}}` - Knowledge base context
**Example Prompt:**
```
You are a professional customer service assistant, skilled at answering product questions.
Product Information: {{product_info}}
Please provide accurate and friendly answers based on user questions. If unsure, honestly inform the user.
User Question: {{user_question}}
```
*Write and configure prompts in the prompt editor*
### 4.2 Add Knowledge Base (Optional)
If you need RAG (Retrieval Augmented Generation) capability:
1. Click **Knowledge Base** in the left menu
2. Create new knowledge base and upload documents
3. Link knowledge base on application orchestration page
4. Configure retrieval parameters
### 4.3 Test Application
1. Input test questions in the **Preview** panel on the right
2. Review AI response effectiveness
3. Adjust prompts and parameters as needed
4. Repeat testing until satisfied
*Test application effectiveness in the preview panel*
### 4.4 Publish Application
After testing:
1. Click **Publish** button in top right
2. Select publishing method:
* **API Call** - Integration via API
* **Embed in Website** - Generate embed code
* **Public Link** - Generate share link
*Select appropriate publishing method*
## Step 5: Monitor and Optimize
### 5.1 View Application Logs
On the application details page:
1. Click the **Logs** tab
2. View all conversation records
3. Analyze user questions and AI responses
4. Discover improvement opportunities
*View and analyze application usage logs*
### 5.2 Monitor API Usage
Log in to [APIMart Console](https://apimart.ai/overview) to view:
* 📊 **API Call Statistics** - Total calls, success rate
* 💰 **Cost Details** - Daily/monthly costs
* 📈 **Usage Trends** - Usage change trends
* 🔍 **Request Logs** - Detailed request records
### 5.3 Optimize Application Performance
Optimize based on monitoring data:
1. **Adjust Model Selection**
* Use `gpt-4o-mini` for simple tasks to reduce costs
* Use `gpt-4o` or `claude-sonnet-4-5` for complex tasks to improve quality
2. **Optimize Prompts**
* Make prompts clearer and more specific
* Add examples to improve effectiveness
* Use chain-of-thought for better reasoning
3. **Configure Caching**
* Enable caching for similar questions
* Reduce API call costs
## Advanced Features
### Using Workflow Orchestration
Dify's workflow feature allows you to:
1. **Conditional Branches** - Execute different logic based on conditions
2. **Multi-model Collaboration** - Combine advantages of multiple models
3. **External Tool Calls** - Call APIs, databases, and other external resources
4. **Variable Passing** - Pass data between different nodes
### Configuring Agent Capabilities
Build intelligent agents with APIMart models:
1. **Tool Calling** - Let AI call external tools
2. **Memory Management** - Maintain long-term conversation memory
3. **Autonomous Decision-making** - AI autonomously plans execution steps
### Multimodal Applications
Leverage APIMart's multimodal capabilities:
1. **Image Understanding** - Use `gpt-4o` or `claude-3` to process images
2. **Image Generation** - Integrate APIMart's image generation API
3. **Voice Processing** - Integrate TTS and STT services
## FAQ
### Q1: Cannot connect to APIMart service?
**Solution:**
1. **Check Base URL**:
* Ensure it's `https://api.apimart.ai/v1` (includes `/v1`)
* Don't add extra paths or omit `/v1`
2. **Verify API Key**:
* Confirm API Key starts with `sk-`
* Check if key is valid in [APIMart Console](https://apimart.ai/keys)
3. **Check Network Connection**:
* Ensure server can access `https://api.apimart.ai`
* Self-hosted versions need to ensure server network connectivity
### Q2: Model response is slow?
**Solution:**
1. **Switch to Faster Models**:
* Use `gpt-4o-mini` instead of `gpt-4o`
* Use `gemini-2.0-flash-exp` for faster response
2. **Optimize Prompt Length**:
* Reduce unnecessary context
* Simplify prompt descriptions
3. **Adjust Knowledge Base Retrieval**:
* Reduce number of retrieved documents
* Increase similarity threshold
### Q3: API calls fail or return errors?
**Common errors and solutions:**
| Error Message | Cause | Solution |
| --------------------------- | ---------------------------- | ---------------------------------------------------- |
| `401 Unauthorized` | Invalid or expired API Key | Re-obtain API Key and update configuration |
| `429 Too Many Requests` | Request rate limit exceeded | Adjust app concurrency settings or wait and retry |
| `500 Internal Server Error` | Temporary server issue | Wait a few minutes and retry |
| `insufficient_quota` | Insufficient account balance | Top up in console |
| `context_length_exceeded` | Input exceeds context length | Reduce input length or use model with larger context |
### Q4: How to reduce API usage costs?
**Cost optimization suggestions:**
1. **Model Selection**:
* Use `gpt-4o-mini` for simple tasks (cost is only 1/10 of `gpt-4o`)
* Consider more economical models for batch tasks
2. **Enable Caching**:
* Return cached results for same questions
* Configure similarity matching in Dify
3. **Optimize Output Length**:
* Set reasonable Max Tokens
* Avoid generating overly long responses
4. **Use Streaming Output**:
* Improve user experience without increasing costs
### Q5: How to handle sensitive data?
**Data security recommendations:**
1. **Use Environment Variables**:
* Don't hardcode API Keys in code
* Use Dify's environment variable feature
2. **Configure Access Control**:
* Set application access permissions
* Enable authentication for API calls
3. **Audit Logs**:
* Regularly check application logs
* Monitor abnormal access patterns
## Best Practices
### 1. Prompt Engineering
**Structured Prompts:**
```
# Role Definition
You are a professional [role description]
# Task Objective
You need to help users [task description]
# Output Requirements
- Requirement 1
- Requirement 2
- Requirement 3
# Input Information
{{user_input}}
```
### 2. Knowledge Base Management
* **Chunking Strategy**: Set reasonable document chunk size (recommended 500-1000 characters)
* **Metadata Tagging**: Add metadata to documents for easier retrieval
* **Regular Updates**: Keep knowledge base content up-to-date
### 3. Error Handling
* **Friendly Messages**: Provide clear error messages to users
* **Fallback Strategy**: Switch to backup model when primary fails
* **Retry Mechanism**: Auto-retry for temporary errors
### 4. Performance Monitoring
* **Set Alerts**: Alert for low balance, high error rates
* **Regular Analysis**: Analyze usage data weekly/monthly
* **Continuous Optimization**: Adjust configuration based on data
## Use Case Examples
### 1. Intelligent Customer Service
**Application Configuration:**
* Model: `gpt-4o-mini` (cost-effective)
* Knowledge Base: Product docs, FAQ
* Features: Auto-answer common questions, escalate complex issues to human
### 2. Content Creation Assistant
**Application Configuration:**
* Model: `gpt-4o` or `claude-sonnet-4-5` (high quality)
* Features: Article generation, rewriting, polishing
* Parameters: Temperature=0.8 (enhance creativity)
### 3. Code Assistant
**Application Configuration:**
* Model: `claude-sonnet-4-5` (excellent for code)
* Features: Code generation, explanation, debugging
* Knowledge Base: Project docs, API docs
### 4. Data Analysis Assistant
**Application Configuration:**
* Model: `gpt-4o` (strong reasoning ability)
* Tools: Python code execution, data visualization
* Features: Data analysis, report generation
## Features
Using Dify + APIMart, you can:
* 🤖 **Quickly Build AI Apps** - Create powerful AI applications without coding
* 📚 **Knowledge Base Enhancement** - RAG technology lets AI answer based on your data
* 🔧 **Flexible Workflows** - Visually orchestrate complex AI logic
* 🎯 **Precise Prompt Management** - Version control and A/B testing
* 📊 **Complete Monitoring & Analytics** - Understand app usage and performance
* 🔌 **Multiple Integration Methods** - API, embedded, WebApp, and more
* 👥 **Team Collaboration** - Support multi-user collaborative development
* 🌐 **Multi-model Support** - Flexibly switch between different AI models
## Support & Help
If you encounter any issues:
* 📚 [APIMart Documentation](https://docs.apimart.ai)
* 📚 [Dify Official Documentation](https://docs.dify.ai)
* 💬 [Discord Community](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 Technical Support: [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
***
Register for APIMart now, get your API key, and build powerful AI applications in Dify!
# Using APIMart in Immersive Translate
Source: https://docs.apimart.ai/en/integrations/platform/immersive-translate
Detailed guide on how to configure and use APIMart API service in the Immersive Translate browser extension. This guide will help you set up APIMart API in Immersive Translate for high-quality AI translation services.
## Prerequisites
Before you begin, please ensure:
1. **Immersive Translate Extension Installed**
Install Immersive Translate from:
* [Chrome Web Store](https://chrome.google.com/webstore/detail/immersive-translate/bpoadfkcbjbfhfodiogcnhhhpibjhbnh)
* [Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/immersive-translate/amkbmndfnliijdhojkpoglbnaaahippg)
* [Firefox Add-ons](https://addons.mozilla.org/firefox/addon/immersive-translate/)
* [Official Website](https://immersivetranslate.com/)
2. **APIMart API Key Obtained**
Login to [APIMart Console](https://apimart.ai/keys) to get your API key (starts with `sk-`)
**Tip:** If you don't have an APIMart account yet, please register at [APIMart](https://apimart.ai) and obtain an API key first.
## Step 1: Open Extension Settings
After installing the Immersive Translate extension:
1. Click the **Immersive Translate** icon in your browser toolbar
2. At the bottom of the popup panel, click the **Settings** button in the lower left corner
3. Enter the Immersive Translate settings page
*Click the Immersive Translate icon in the browser toolbar, then click the "Settings" button at the bottom left*
## Step 2: Configure Translation Service
### 2.1 Enter Translation Service Settings
On the settings page:
1. Find the **"Translation Services"** option in the left menu
2. Click to enter the translation service configuration page
*Find the "Translation Services" option in the settings page*
### 2.2 Add Custom Translation Service
On the translation services list page:
1. Click the **+ Add Custom Translation Service** button at the top
2. Fill in APIMart API information in the configuration form
**Tip:** Immersive Translate supports adding OpenAI-compatible custom translation services, and APIMart is fully compatible with this format.
### 2.3 Configure APIMart API Information
Fill in the following configuration information:
| Configuration | Value | Description |
| ----------------------------------- | ------------------------------------------------ | ------------------------------------------ |
| **Custom Translation Service Name** | `APIMart` | Customizable, for easy identification |
| **APIKEY** | `sk-xxxxxxxxxxxx` | Your APIMart API key |
| **Model** | `gpt-4o-mini` or others | Select from dropdown list |
| **Custom API Endpoint** | `https://api.apimart.ai/api/v1/chat/completions` | Complete API endpoint address |
| **Max Requests Per Second** | `5` | Control request frequency, recommended 3-5 |
**Configuration Notes:**
* **APIKEY**: Must be obtained from [APIMart Console](https://apimart.ai/keys) and start with `sk-`
* **API Endpoint**: Must use the complete path `https://api.apimart.ai/api/v1/chat/completions`
* **Model Selection**: Recommend `gpt-4o-mini` (cost-effective) or `gpt-5` (best quality)
* **Request Frequency**: Setting to 5 balances speed and stability
*Fill in APIMart custom translation service configuration*
## Step 3: Save and Select Translation Service
After completing the configuration:
1. Click the **Save** button at the bottom of the configuration page
2. Return to the extension panel, select **APIMart** from the **Translation Service** dropdown menu
3. You can select translation style (such as "General") in **AI Expert**
### Recommended Models
Different models are suitable for different translation scenarios:
**Available Models:**
* **gpt-5** - Latest model, highest translation quality ⭐ Recommended
* **gpt-4o** - High-quality translation, fast speed
* **gpt-4o-mini** - Cost-effective, suitable for large-scale translation 💰 Best Value
* **claude-sonnet-4-5-20250929** - Good for literary translation
* **claude-haiku-4-5-20251001** - Fast translation, cost-effective
**Translation Scenario Recommendations:**
* 📚 **Professional Docs, Technical Docs:** `gpt-5`, `gpt-4o`
* 📰 **News Articles, Blogs:** `gpt-4o`, `claude-sonnet-4-5-20250929`
* 💬 **Daily Web Browsing:** `gpt-4o-mini`, `claude-haiku-4-5-20251001`
* 🎨 **Literary Works, Creative Content:** `claude-sonnet-4-5-20250929`, `gpt-5`
* 💰 **High-Volume, Cost-Sensitive:** `gpt-4o-mini`
## Step 4: Start Using Translation
After configuration is complete, you can start using Immersive Translate:
### 4.1 Web Page Translation
1. Open any foreign language webpage
2. Click the Immersive Translate icon in the browser toolbar
3. Select **Translate this page** or use the shortcut (default: `Alt+A`)
*Immersive Translate webpage effect example*
*Selection translation feature example*
### 4.3 PDF Translation
Immersive Translate supports online PDF file translation:
1. Open a PDF file in your browser (online PDF)
2. Click the Immersive Translate icon to open the extension panel
3. Click the **Click to translate PDF (Alt+A)** button
4. Wait for translation to complete, PDF will display bilingual comparison
*PDF document bilingual translation example*
**PDF Translation Support:**
* ✅ Supports online PDF files (such as planetebook.com, arXiv.org, etc.)
* ✅ Maintains original layout, displays bilingual comparison
* ✅ Supports selecting translation regions
* ❌ Local PDFs need to be uploaded to web viewer
### 4.4 Video Subtitle Translation
Supports real-time subtitle translation for mainstream video platforms:
1. Open YouTube, Netflix and other video platforms
2. Play video, Immersive Translate automatically recognizes subtitles
3. Automatically generates bilingual subtitle display
**Supported Platforms:**
* 🎬 YouTube
* 📺 Netflix
* 🎥 Coursera
* 📹 Udemy
* 🎓 edX
## Advanced Features
### Custom Translation Rules
Rich personalization options can be configured in settings:
**Basic Settings:**
* **Translation Service** - Select default translation service (APIMart)
* **AI Expert** - Select translation style (General, Professional, Literary, etc.)
* **AI Terminology** - Manage professional terminology translation
**Advanced Options:**
* **Website Rules** - Set automatic translation rules for specific websites
* **Translation Style** - Customize translation color, font and other display styles
* **Mouse Hover Settings** - Configure Ctrl + mouse hover to show original text
* **Word Selection Translation** - Set translation behavior after selecting text
* **Input Box Enhancement** - Enable real-time translation in input boxes
### Keyboard Shortcuts
Immersive Translate provides convenient keyboard shortcuts:
| Function | Default Shortcut | Description |
| ------------------------------ | --------------------- | ------------------------------------------- |
| **Translate Webpage/PDF** | `Alt+A` | Start translating current page or PDF |
| **Show Original** | `Alt+A` again | Toggle to show original text |
| **Word Translation Panel** | `Alt+W` | Open word selection translation window |
| **Switch Translation Service** | Configure in settings | Quickly switch between translation services |
**Shortcut Tip:** All shortcuts can be customized in extension settings, choose the key combination that best suits your habits.
### Translation Modes
Immersive Translate offers multiple flexible translation display modes:
| Mode | Description | Use Case |
| ------------------------ | -------------------------------------------- | ------------------------------------------ |
| **Bilingual Comparison** | Original and translated paragraphs alternate | Learning, comparative reading 📚 |
| **Mouse Hover** | Show translation on paragraph hover | Occasional translation viewing 👆 |
| **Only This Website** | Enable translation only on current site | Specific website frequent use 🌐 |
| **Word Selection** | Show translation after selecting text | Precise translation of specific content ✍️ |
## FAQ
### Q1: Translation not working after configuration?
**Solutions:**
1. **Check Translation Service Selection**:
* Open extension panel, confirm **APIMart** is selected in "Translation Service" dropdown
* If you can't see APIMart, return to settings page to check if configuration is saved
2. **Check API Key**:
* Confirm APIKEY is correct and starts with `sk-`
* Check if key is valid and has balance at [APIMart Console](https://apimart.ai/keys)
3. **Check API Endpoint**:
* Must fill in complete path: `https://api.apimart.ai/api/v1/chat/completions`
* Note it's not `/api/v1` but `/api/v1/chat/completions`
4. **Check Model Name**:
* Confirm model name is correct (like `gpt-4o-mini`, `gpt-5`)
* Model names are case-sensitive
### Q2: Translation slow or timing out?
**Solutions:**
1. **Adjust Max Requests Per Second**:
* In configuration, reduce "Max Requests Per Second" to `3`
* Avoid too many concurrent requests causing timeout
2. **Switch to Faster Model**:
* Use `gpt-4o-mini` (fast and economical)
* Or use `claude-haiku-4-5-20251001`
3. **Check Network Connection**:
* Ensure stable network, avoid frequent disconnections
* For large pages, recommend translating in sections
4. **Disable Unnecessary Features**:
* Temporarily disable "Enable AI Illustration" and other enhanced features
* Reduce API call count
### Q3: Translation quality not ideal?
**Solutions:**
1. **Choose Higher Quality Model**:
* Use `gpt-5` (latest and strongest) or `gpt-4o` (high quality)
* For literary and professional content, recommend `claude-sonnet-4-5-20250929`
2. **Adjust AI Expert Settings**:
* Select appropriate "AI Expert" in extension panel
* Choose "Professional" for technical docs, "General" for daily content
3. **Use Terminology Library**:
* Configure "AI Terminology" in settings
* Add preferred translations for professional terms, ensure consistency
4. **Enable AI Context Enhancement**:
* Enable "AI Smart Context" in custom service configuration
* Provides more accurate contextual understanding
### Q4: Some websites cannot be translated?
**Solutions:**
1. **Check Website Compatibility**:
* Some dynamically loaded websites may need page refresh
* SPAs may need manual translation triggering
2. **Add Website Rules**:
* Add specific website configuration in "Website Rules" in settings
* Specify translation areas and exclusion areas
3. **Try Different Translation Modes**:
* Switch to "Mouse Hover" or "Word Selection" mode
* Some websites work better in specific modes
### Q5: How to view translation consumption?
Login to [APIMart Console](https://apimart.ai/overview) to view detailed statistics:
* 📊 **API Call Statistics** - Real-time view of call count and frequency
* 💰 **Cost Details** - Detailed cost record for each call
* 📈 **Usage Trends** - View usage by date/model
* 🔍 **Request Logs** - Detailed request and response records
## Usage Tips
### 1. Smart Translation Service Selection
Choose appropriate models for different scenarios:
* **📚 Academic Papers, Technical Docs**: Use `gpt-5` for accuracy
* **📰 News Articles, Blogs**: Use `gpt-4o` to balance quality and speed
* **💬 Social Media, Daily Browsing**: Use `gpt-4o-mini` to save costs
* **🎨 Literary Works, Creative Content**: Use `claude-sonnet-4-5-20250929`
### 2. Configure Website Auto-Translation
Set auto-translation rules for frequently visited websites:
1. Open Settings → **Website Rules**
2. Add website domain (like `github.com`)
3. Set to "Always Translate" or "Never Translate"
4. After saving, rules apply automatically when visiting the site
### 3. Use Word Selection for Precise Queries
For specific content within large text blocks:
1. Enable "Word Selection Translation" feature
2. Select text that needs translation
3. View precise translation results
4. Avoid translating entire page, save API calls
### 4. Optimize Translation Quality
**Configure Terminology Library**:
* Add professional terms in settings
* Ensure consistency in technical terminology translation
* Support multiple terminology library categories
**Choose Appropriate AI Expert**:
* Select "Professional" or "Technical" for technical docs
* Select "General" for daily content
* Select "Literary" or "Creative" for literary works
### 5. Save API Costs
**Cost Control Strategy**:
* ✅ Use `gpt-4o-mini` as default model for daily browsing
* ✅ Only switch to `gpt-5` for important documents
* ✅ Configure "Max Requests Per Second" to 3-5, avoid limits
* ✅ Use "Only This Website" feature to control translation scope
* ✅ Select needed page ranges when translating PDFs
* ❌ Avoid frequently refreshing already translated pages
## Features
Using Immersive Translate + APIMart, you can:
* 🌐 **Webpage Translation** - Bilingual comparison display, maintains original layout
* 📄 **PDF Translation** - Supports online PDF document translation
* 🎬 **Video Subtitles** - YouTube, Netflix and other platforms' bilingual subtitles
* ✍️ **Word Selection Translation** - Select and translate, quick understanding
* 📧 **Input Enhancement** - Direct translation in input boxes
* 📱 **Full Platform Support** - Chrome, Edge, Firefox, Safari, etc.
* 🎨 **Custom Styles** - Adjust translation display effects
* ⚡ **Quick Operations** - Rich keyboard shortcut support
## Support and Help
If you encounter any issues during use:
* 📚 [APIMart Documentation Center](https://docs.apimart.ai)
* 📚 [Immersive Translate Documentation](https://immersivetranslate.com/docs/)
* 💬 [Discord Community](https://discord.gg/V8zqssyZ5c)
* 🐦 [Twitter @APIMart\_](https://x.com/APIMart_)
* 📧 Technical Support: [zhihong@apimart.ai](mailto:zhihong@apimart.ai)
***
Register for APIMart now, get your API key, and enjoy high-quality translation services!
# Quick Start
Source: https://docs.apimart.ai/en/quickstart
Quickly start using our API services
# Quick Start
Welcome to our API services! This guide helps you quickly get started with image and video generation.
## Step 1: Get an API Key
1. Visit the [API Key Management page](https://apimart.ai/keys)
2. Sign in to your account
3. Create a new API key
On the API Keys page, click the **Create API Key** button in the top-right corner.
In the dialog that appears, enter a **Name** for the key, optionally configure the quota (Unlimited Quota), model limits (Enable Model Limits) and an IP whitelist, then click **Create Key**.
4. Save your key securely
## Step 2: Choose a Model
We provide multiple AI models to choose from. Visit the [Model Market](https://apimart.ai/en/model) to browse all available models and their pricing.
### Text Generation Models
* **GPT-4o**: Powerful dialogue and text generation capabilities
* **Claude**: High-performance conversational model by Anthropic
* **Gemini**: Google's multimodal large language model
### Image Generation Models
* **GPT-4o-image**: High‑quality image generation
### Video Generation Models
* **Sora2**: Professional video generation
## Step 3: Send a Request
### Text generation example
```bash theme={null}
curl -X POST https://api.apimart.ai/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": "Hello, please introduce yourself"
}
]
}'
```
### Image generation example
```bash theme={null}
curl -X POST https://api.apimart.ai/v1/images/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-image",
"prompt": "A cute panda",
"size": "1:1",
"n": 1
}'
```
### Video generation example
```bash theme={null}
curl -X POST https://api.apimart.ai/v1/videos/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "sora-2",
"prompt": "Waves crashing against the shore",
"duration": 15,
"aspect_ratio": "16:9"
}'
```
## Step 4: Check Task Status
Because we use asynchronous processing, you need to query task status to obtain results.
```bash theme={null}
curl -X GET https://api.apimart.ai/v1/tasks/YOUR_TASK_ID \
-H "Authorization: Bearer YOUR_API_KEY"
```
## What’s Next
Learn more about all available API endpoints.
Learn how to integrate the API into your application.