Skip to main content

Images and video

Images and video

POST /v1/images for image generation; POST /v1/videos with polling for video jobs.

posthttps://api.pre.dev/v1/imagesTry it

Both endpoints take a model and a prompt and return generated images or video. List the models with GET /v1/images/models and GET /v1/videos/models; both lists are free and not rate-limited and include a predev price object per row.

Images

POST /v1/images returns generated images synchronously and is charged when the response is returned.

curl --fail-with-body https://api.pre.dev/v1/images \
  -H "Authorization: Bearer $PREDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "recraft/recraft-v4.1-flash", "prompt": "A lighthouse at dawn, watercolor", "n": 1, "aspect_ratio": "1:1"}'

Pick another model from GET /v1/images/models; each row lists the parameters it accepts in supported_parameters, and some models edit an input image rather than start from a prompt.

To edit an image or draw from one, pass it in input_references. Each item is a URL or data: URL string, or {"type": "image_url", "image_url": {"url": "..."}}.

curl --fail-with-body https://api.pre.dev/v1/images \
  -H "Authorization: Bearer $PREDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "google/gemini-3.1-flash-lite-image", "prompt": "The same lighthouse at night, under a sky full of stars", "input_references": ["https://example.com/lighthouse.png"]}'

Use credits_per_image or the other predev prices in the model row to estimate cost; the actual charge follows the call’s metered usage, like every other call.

Video

Video generation is asynchronous:

  1. POST /v1/videos submits the job and returns it with its id and a polling_url.
  2. GET /v1/videos/{id} reports status. polling_url is this same URL, ending with the job’s id, so polling either one works.
  3. GET /v1/videos/{id}/content returns the finished video.
ID=$(curl --fail-with-body -s https://api.pre.dev/v1/videos \
  -H "Authorization: Bearer $PREDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "bytedance/seedance-2.0-mini", "prompt": "A paper boat drifting down a rain gutter", "duration": 4, "resolution": "480p"}' | jq -r '.id')

# poll until the status is terminal
while :; do
  STATUS=$(curl --fail-with-body -s "https://api.pre.dev/v1/videos/$ID" -H "Authorization: Bearer $PREDEV_API_KEY" | jq -r '.status')
  case "$STATUS" in completed|failed|cancelled|expired) break ;; esac
  sleep 5
done

# then download
curl --fail-with-body "https://api.pre.dev/v1/videos/$ID/content" \
  -H "Authorization: Bearer $PREDEV_API_KEY" -o video.mp4

Submitting a job needs at least 10 credits available. The job is charged once it finishes, not at submission: on the first status poll that reports completion, on the /content download if you never polled, or by pre.dev afterwards if you stopped polling. Poll until the status is terminal (completed, failed, cancelled or expired) before reading /content. Poll and download with the job’s id from the submit response.

Jobs belong to the workspace that created them; another workspace’s job id returns 404.

curl -X POST "https://api.pre.dev/v1/images" \  -H "Content-Type: application/json" \  -d '{    "model": "recraft/recraft-v4.1-flash",    "prompt": "A lighthouse at dawn, watercolor",    "n": 1,    "aspect_ratio": "1:1"  }'
const body = JSON.stringify({  "model": "recraft/recraft-v4.1-flash",  "prompt": "A lighthouse at dawn, watercolor",  "n": 1,  "aspect_ratio": "1:1"})fetch("https://api.pre.dev/v1/images", {  method: "POST",  headers: {    "Content-Type": "application/json"  },  body})
package mainimport (  "fmt"  "net/http"  "io/ioutil"  "strings")func main() {  url := "https://api.pre.dev/v1/images"  body := strings.NewReader(`{    "model": "recraft/recraft-v4.1-flash",    "prompt": "A lighthouse at dawn, watercolor",    "n": 1,    "aspect_ratio": "1:1"  }`)  req, _ := http.NewRequest("POST", url, body)  req.Header.Add("Content-Type", "application/json")  res, _ := http.DefaultClient.Do(req)  defer res.Body.Close()  body, _ := ioutil.ReadAll(res.Body)  fmt.Println(res)  fmt.Println(string(body))}
import requestsurl = "https://api.pre.dev/v1/images"body = """{  "model": "recraft/recraft-v4.1-flash",  "prompt": "A lighthouse at dawn, watercolor",  "n": 1,  "aspect_ratio": "1:1"}"""response = requests.request("POST", url, data = body, headers = {  "Content-Type": "application/json"})print(response.text)
import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.net.http.HttpResponse.BodyHandlers;import java.time.Duration;import java.net.http.HttpRequest.BodyPublishers;var body = BodyPublishers.ofString("""{  "model": "recraft/recraft-v4.1-flash",  "prompt": "A lighthouse at dawn, watercolor",  "n": 1,  "aspect_ratio": "1:1"}""");HttpClient client = HttpClient.newBuilder()  .connectTimeout(Duration.ofSeconds(10))  .build();HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()  .uri(URI.create("https://api.pre.dev/v1/images"))  .header("Content-Type", "application/json")  .POST(body)  .build();try {  HttpResponse<String> response = client.send(requestBuilder.build(), BodyHandlers.ofString());  System.out.println("Status code: " + response.statusCode());  System.out.println("Response body: " + response.body());} catch (Exception e) {  e.printStackTrace();}
using System;using System.Net.Http;using System.Text;var body = new StringContent("""{  "model": "recraft/recraft-v4.1-flash",  "prompt": "A lighthouse at dawn, watercolor",  "n": 1,  "aspect_ratio": "1:1"}""", Encoding.UTF8, "application/json");var client = new HttpClient();var response = await client.PostAsync("https://api.pre.dev/v1/images", body);var responseBody = await response.Content.ReadAsStringAsync();
use reqwest::{Result, Client};async fn main() -> Result<()> {  let client = Client::new();  let url = "https://api.pre.dev/v1/images";  let body = r#"{    "model": "recraft/recraft-v4.1-flash",    "prompt": "A lighthouse at dawn, watercolor",    "n": 1,    "aspect_ratio": "1:1"  }"#;  let res = client    .post(url)    .header("Content-Type", "application/json")    .body(body)    .send()    .await?    .text()    .await?;  println!("{}", res);  Ok(())}
{  "created": 1790500000,  "data": [    {      "b64_json": "iVBORw0KGgoAAAANSUhEUgAA…",      "media_type": "image/png"    }  ]}
POST
/v1/images

Authorization

AuthorizationBearer <token>

The workspace API key (pdk_…) from Integrations → Built-in in the pre.dev dashboard.

In: header

Header Parameters

x-predev-project-id?string

Attribute this call to one of the workspace's projects. An id the workspace does not own is ignored.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

Generated images as base64. With stream: true on a model that supports it, partial images arrive as server-sent events.

TypeScript Definitions

Use the response body type in TypeScript.

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

Was this page helpful?