curl --request POST \
--url https://api.ephone.ai/midjourney/video \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"image": "https://example.com/first-frame.png"
}
'import requests
url = "https://api.ephone.ai/midjourney/video"
payload = { "image": "https://example.com/first-frame.png" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({image: 'https://example.com/first-frame.png'})
};
fetch('https://api.ephone.ai/midjourney/video', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.ephone.ai/midjourney/video"
payload := strings.NewReader("{\n \"image\": \"https://example.com/first-frame.png\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"task_id": "mj-6f1c2b0e9a7d4e2fb1c3d5e7f9a1b2c3",
"action": "video",
"status": "submitted",
"created_at": 1792000000
}{
"error": {
"code": "invalid_request",
"message": "index must be between 1 and 4"
}
}{
"error": {
"code": "unauthorized",
"message": "Invalid API key"
}
}{
"error": {
"code": "insufficient_quota",
"message": "Insufficient balance"
}
}{
"error": {
"code": "queue_full",
"message": "Queue is full, please try again later"
}
}{
"error": {
"code": "upstream_error",
"message": "The service is temporarily unavailable, please retry"
}
}Image to Video
Turn an image into a 5-second video, with 480p / 720p, motion level and batch size.
curl --request POST \
--url https://api.ephone.ai/midjourney/video \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"image": "https://example.com/first-frame.png"
}
'import requests
url = "https://api.ephone.ai/midjourney/video"
payload = { "image": "https://example.com/first-frame.png" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({image: 'https://example.com/first-frame.png'})
};
fetch('https://api.ephone.ai/midjourney/video', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.ephone.ai/midjourney/video"
payload := strings.NewReader("{\n \"image\": \"https://example.com/first-frame.png\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"task_id": "mj-6f1c2b0e9a7d4e2fb1c3d5e7f9a1b2c3",
"action": "video",
"status": "submitted",
"created_at": 1792000000
}{
"error": {
"code": "invalid_request",
"message": "index must be between 1 and 4"
}
}{
"error": {
"code": "unauthorized",
"message": "Invalid API key"
}
}{
"error": {
"code": "insufficient_quota",
"message": "Insufficient balance"
}
}{
"error": {
"code": "queue_full",
"message": "Queue is full, please try again later"
}
}{
"error": {
"code": "upstream_error",
"message": "The service is temporarily unavailable, please retry"
}
}POST /v1/task/submit with model set to midjourney-video and the parameters inside input. Both behave and bill the same.notify_hook when submitting. When the task succeeds, actions in the result lists what you can do next through Image Actions.
This endpoint starts from your own image. To start from an image in an existing task, or to extend a video, call Image Actions with action set to video or video-extend.Authorizations
Send your API key in the Authorization: Bearer YOUR_API_KEY header.
Body
First Frame: An image URL (publicly reachable) or a base64 data URI, up to 20 MB each.
Prompt: Optional: describe the motion. Without it, motion is generated automatically.
6000Resolution: 480p (default) or 720p (3.2x price).
480p, 720p Motion: low (default, subtle motion) or high (large camera motion).
low, high Batch Size: Videos per task: 1 (default), 2 or 4; priced by count.
1, 2, 4 End Frame: Optional end frame. An image URL (publicly reachable) or a base64 data URI, up to 20 MB each.
Loop: Make a seamless loop; cannot be combined with end_image.
Speed: Video supports fast and turbo only. You can also write --fast / --turbo in the prompt; this field wins.
fast, turbo Notify hook: when the task ends, the same content as the fetch result is POSTed to this URL (a public http / https URL). Omit it to poll instead.
Was this page helpful?