curl --request POST \
--url https://api.developer.pixelcut.ai/v1/video/loop \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"image_url": "https://cdn3.pixelcut.app/product.jpg",
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......",
"prompt": "clothes blowing subtly in the wind, person slightly moving",
"duration": 5,
"resolution": "768p",
"include_audio": true,
"motion": "subtle"
}
'import requests
url = "https://api.developer.pixelcut.ai/v1/video/loop"
payload = {
"image_url": "https://cdn3.pixelcut.app/product.jpg",
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......",
"prompt": "clothes blowing subtly in the wind, person slightly moving",
"duration": 5,
"resolution": "768p",
"include_audio": True,
"motion": "subtle"
}
headers = {
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
image_url: 'https://cdn3.pixelcut.app/product.jpg',
image: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......',
prompt: 'clothes blowing subtly in the wind, person slightly moving',
duration: 5,
resolution: '768p',
include_audio: true,
motion: 'subtle'
})
};
fetch('https://api.developer.pixelcut.ai/v1/video/loop', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.developer.pixelcut.ai/v1/video/loop",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'image_url' => 'https://cdn3.pixelcut.app/product.jpg',
'image' => 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......',
'prompt' => 'clothes blowing subtly in the wind, person slightly moving',
'duration' => 5,
'resolution' => '768p',
'include_audio' => true,
'motion' => 'subtle'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.developer.pixelcut.ai/v1/video/loop"
payload := strings.NewReader("{\n \"image_url\": \"https://cdn3.pixelcut.app/product.jpg\",\n \"image\": \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......\",\n \"prompt\": \"clothes blowing subtly in the wind, person slightly moving\",\n \"duration\": 5,\n \"resolution\": \"768p\",\n \"include_audio\": true,\n \"motion\": \"subtle\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<api-key>")
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))
}HttpResponse<String> response = Unirest.post("https://api.developer.pixelcut.ai/v1/video/loop")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"image_url\": \"https://cdn3.pixelcut.app/product.jpg\",\n \"image\": \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......\",\n \"prompt\": \"clothes blowing subtly in the wind, person slightly moving\",\n \"duration\": 5,\n \"resolution\": \"768p\",\n \"include_audio\": true,\n \"motion\": \"subtle\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.developer.pixelcut.ai/v1/video/loop")
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["Content-Type"] = 'application/json'
request.body = "{\n \"image_url\": \"https://cdn3.pixelcut.app/product.jpg\",\n \"image\": \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......\",\n \"prompt\": \"clothes blowing subtly in the wind, person slightly moving\",\n \"duration\": 5,\n \"resolution\": \"768p\",\n \"include_audio\": true,\n \"motion\": \"subtle\"\n}"
response = http.request(request)
puts response.read_body{
"job_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"status": "pending"
}{
"error": "File size too large",
"error_code": "file_size_too_large"
}{
"error": "API Token not found",
"error_code": "invalid_auth_token"
}{
"error": "Insufficient credits available",
"error_code": "insufficient_api_credits"
}{
"error": "Too many requests",
"error_code": "rate_limit_exceeded"
}Looping Video
Turns a single still image into a seamless 5-15 second looping MP4 video. The subject, composition, and lighting are preserved, and the video loops endlessly with no visible jump or cut. The camera stays fixed - no pans, zooms, tilts, or reframing. Choose the motion style with motion: subtle (default) adds gentle, natural movement, while spin shows the subject from every side through a full 360-degree revolution that ends on the starting view. Processing is asynchronous: poll the job status endpoint returned in the Location header to retrieve the result.
Provide exactly one image source: a multipart image file, a base64/data-URL image, or a remote image_url. Requests with no image source or more than one are rejected.
Pricing:
- 480p: 8 credits ($0.08) per second
- 768p: 16 credits ($0.16) per second
- Audio does not change the price.
Input Image Limits:
- Max size: 25MB
- Min resolution: 64x64px
- Max resolution: 6000x6000px
- Supported formats: JPEG, PNG
curl --request POST \
--url https://api.developer.pixelcut.ai/v1/video/loop \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"image_url": "https://cdn3.pixelcut.app/product.jpg",
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......",
"prompt": "clothes blowing subtly in the wind, person slightly moving",
"duration": 5,
"resolution": "768p",
"include_audio": true,
"motion": "subtle"
}
'import requests
url = "https://api.developer.pixelcut.ai/v1/video/loop"
payload = {
"image_url": "https://cdn3.pixelcut.app/product.jpg",
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......",
"prompt": "clothes blowing subtly in the wind, person slightly moving",
"duration": 5,
"resolution": "768p",
"include_audio": True,
"motion": "subtle"
}
headers = {
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
image_url: 'https://cdn3.pixelcut.app/product.jpg',
image: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......',
prompt: 'clothes blowing subtly in the wind, person slightly moving',
duration: 5,
resolution: '768p',
include_audio: true,
motion: 'subtle'
})
};
fetch('https://api.developer.pixelcut.ai/v1/video/loop', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.developer.pixelcut.ai/v1/video/loop",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'image_url' => 'https://cdn3.pixelcut.app/product.jpg',
'image' => 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......',
'prompt' => 'clothes blowing subtly in the wind, person slightly moving',
'duration' => 5,
'resolution' => '768p',
'include_audio' => true,
'motion' => 'subtle'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.developer.pixelcut.ai/v1/video/loop"
payload := strings.NewReader("{\n \"image_url\": \"https://cdn3.pixelcut.app/product.jpg\",\n \"image\": \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......\",\n \"prompt\": \"clothes blowing subtly in the wind, person slightly moving\",\n \"duration\": 5,\n \"resolution\": \"768p\",\n \"include_audio\": true,\n \"motion\": \"subtle\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<api-key>")
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))
}HttpResponse<String> response = Unirest.post("https://api.developer.pixelcut.ai/v1/video/loop")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"image_url\": \"https://cdn3.pixelcut.app/product.jpg\",\n \"image\": \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......\",\n \"prompt\": \"clothes blowing subtly in the wind, person slightly moving\",\n \"duration\": 5,\n \"resolution\": \"768p\",\n \"include_audio\": true,\n \"motion\": \"subtle\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.developer.pixelcut.ai/v1/video/loop")
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["Content-Type"] = 'application/json'
request.body = "{\n \"image_url\": \"https://cdn3.pixelcut.app/product.jpg\",\n \"image\": \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/......\",\n \"prompt\": \"clothes blowing subtly in the wind, person slightly moving\",\n \"duration\": 5,\n \"resolution\": \"768p\",\n \"include_audio\": true,\n \"motion\": \"subtle\"\n}"
response = http.request(request)
puts response.read_body{
"job_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"status": "pending"
}{
"error": "File size too large",
"error_code": "file_size_too_large"
}{
"error": "API Token not found",
"error_code": "invalid_auth_token"
}{
"error": "Insufficient credits available",
"error_code": "insufficient_api_credits"
}{
"error": "Too many requests",
"error_code": "rate_limit_exceeded"
}Authorizations
All API requests require a valid api key. Include your token as a HTTP request header in the following format: X-API-Key: skXXXXXXXXXXXXXXXX. You can obtain an api key by signing up for developer access in your Pixelcut account.
Body
URL of the image to be processed.
"https://cdn3.pixelcut.app/product.jpg"
Base64 encoded representation of the image to be processed.
Optional creative direction for the motion (e.g. what should move subtly). Directions requesting camera movement, cuts, new objects, or scene changes are ignored.
1000"clothes blowing subtly in the wind, person slightly moving"
Length of the looping video in whole seconds (5-15).
5 <= x <= 155
Output resolution of the looping video. 480p costs 8 credits per second; 768p costs 16 credits per second.
480p, 768p "768p"
Whether the generated MP4 keeps its audio track. When false, the audio track is stripped and the result is guaranteed to contain no audio stream. Audio does not change the price.
true
Motion style. subtle adds gentle, natural movement that returns to the starting pose. spin shows the subject from every side through one full 360-degree revolution that ends on the starting view. People and isolated products on a plain background turn in place while the camera stays fixed; an object photographed in a real setting stays still and the camera orbits around it instead. Does not change the price.
subtle, spin "subtle"