curl --request POST \
--url https://api.ekly.ai/v1/images \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"aspect_ratio": "16:9",
"generate_image_count": 1,
"model": "gemini-2.5-flash-image",
"prompt": "A red fox resting in autumn leaves, soft morning light"
}
'import requests
url = "https://api.ekly.ai/v1/images"
payload = {
"aspect_ratio": "16:9",
"generate_image_count": 1,
"model": "gemini-2.5-flash-image",
"prompt": "A red fox resting in autumn leaves, soft morning light"
}
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({
aspect_ratio: '16:9',
generate_image_count: 1,
model: 'gemini-2.5-flash-image',
prompt: 'A red fox resting in autumn leaves, soft morning light'
})
};
fetch('https://api.ekly.ai/v1/images', 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.ekly.ai/v1/images",
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([
'aspect_ratio' => '16:9',
'generate_image_count' => 1,
'model' => 'gemini-2.5-flash-image',
'prompt' => 'A red fox resting in autumn leaves, soft morning light'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.ekly.ai/v1/images"
payload := strings.NewReader("{\n \"aspect_ratio\": \"16:9\",\n \"generate_image_count\": 1,\n \"model\": \"gemini-2.5-flash-image\",\n \"prompt\": \"A red fox resting in autumn leaves, soft morning light\"\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))
}HttpResponse<String> response = Unirest.post("https://api.ekly.ai/v1/images")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"aspect_ratio\": \"16:9\",\n \"generate_image_count\": 1,\n \"model\": \"gemini-2.5-flash-image\",\n \"prompt\": \"A red fox resting in autumn leaves, soft morning light\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ekly.ai/v1/images")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"aspect_ratio\": \"16:9\",\n \"generate_image_count\": 1,\n \"model\": \"gemini-2.5-flash-image\",\n \"prompt\": \"A red fox resting in autumn leaves, soft morning light\"\n}"
response = http.request(request)
puts response.read_body{
"created_at": "2023-11-07T05:31:56Z",
"id": "6f1c2d3e-9a0b-4c7d-8e1f-2a3b4c5d6e7f",
"model": "seedance-2-5-fal",
"prompt": "<string>",
"status": "pending",
"type": "image",
"completed_at": "2023-11-07T05:31:56Z",
"credits_charged": 123,
"error": {
"code": "<string>",
"message": "<string>"
},
"idempotency_key": "<string>",
"outputs": [
{
"url": "<string>",
"asset_id": "<string>",
"content_type": "video/mp4",
"duration_seconds": 123,
"height": 123,
"width": 123
}
]
}{
"error": {
"code": "unauthenticated",
"message": "This API key is not valid. Create a new one in Settings → Team.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "payment_required",
"message": "Insufficient credits: this generation needs 39.6 credits and 12.0 are available.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "forbidden",
"message": "API keys can only call the /v1 API.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "conflict",
"message": "This idempotency key was already used with a different request.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "validation_error",
"details": [
{
"loc": [
"body",
"model"
],
"msg": "Field required",
"type": "missing"
}
],
"message": "Request validation failed.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded; retry after 12s.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}Generate images
Submits an image generation. Reference inputs such as reference_images take asset ids from POST /v1/uploads or an earlier output. Returns immediately with status: pending; credits are reserved now and settled when the job finishes. Poll GET /v1/generations/{id} until completed or failed.
curl --request POST \
--url https://api.ekly.ai/v1/images \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"aspect_ratio": "16:9",
"generate_image_count": 1,
"model": "gemini-2.5-flash-image",
"prompt": "A red fox resting in autumn leaves, soft morning light"
}
'import requests
url = "https://api.ekly.ai/v1/images"
payload = {
"aspect_ratio": "16:9",
"generate_image_count": 1,
"model": "gemini-2.5-flash-image",
"prompt": "A red fox resting in autumn leaves, soft morning light"
}
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({
aspect_ratio: '16:9',
generate_image_count: 1,
model: 'gemini-2.5-flash-image',
prompt: 'A red fox resting in autumn leaves, soft morning light'
})
};
fetch('https://api.ekly.ai/v1/images', 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.ekly.ai/v1/images",
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([
'aspect_ratio' => '16:9',
'generate_image_count' => 1,
'model' => 'gemini-2.5-flash-image',
'prompt' => 'A red fox resting in autumn leaves, soft morning light'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.ekly.ai/v1/images"
payload := strings.NewReader("{\n \"aspect_ratio\": \"16:9\",\n \"generate_image_count\": 1,\n \"model\": \"gemini-2.5-flash-image\",\n \"prompt\": \"A red fox resting in autumn leaves, soft morning light\"\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))
}HttpResponse<String> response = Unirest.post("https://api.ekly.ai/v1/images")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"aspect_ratio\": \"16:9\",\n \"generate_image_count\": 1,\n \"model\": \"gemini-2.5-flash-image\",\n \"prompt\": \"A red fox resting in autumn leaves, soft morning light\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ekly.ai/v1/images")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"aspect_ratio\": \"16:9\",\n \"generate_image_count\": 1,\n \"model\": \"gemini-2.5-flash-image\",\n \"prompt\": \"A red fox resting in autumn leaves, soft morning light\"\n}"
response = http.request(request)
puts response.read_body{
"created_at": "2023-11-07T05:31:56Z",
"id": "6f1c2d3e-9a0b-4c7d-8e1f-2a3b4c5d6e7f",
"model": "seedance-2-5-fal",
"prompt": "<string>",
"status": "pending",
"type": "image",
"completed_at": "2023-11-07T05:31:56Z",
"credits_charged": 123,
"error": {
"code": "<string>",
"message": "<string>"
},
"idempotency_key": "<string>",
"outputs": [
{
"url": "<string>",
"asset_id": "<string>",
"content_type": "video/mp4",
"duration_seconds": 123,
"height": 123,
"width": 123
}
]
}{
"error": {
"code": "unauthenticated",
"message": "This API key is not valid. Create a new one in Settings → Team.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "payment_required",
"message": "Insufficient credits: this generation needs 39.6 credits and 12.0 are available.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "forbidden",
"message": "API keys can only call the /v1 API.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "conflict",
"message": "This idempotency key was already used with a different request.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "validation_error",
"details": [
{
"loc": [
"body",
"model"
],
"msg": "Field required",
"type": "missing"
}
],
"message": "Request validation failed.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded; retry after 12s.",
"trace_id": "c3746d5302dc4be6b2e8fa99fa762a8c"
}
}Authorizations
An organization API key created in Settings → Team, sent as Authorization: Bearer <key>.
Headers
Reuse the same value when retrying the same request; a repeat returns the original generation without charging again. Reusing it with a different body returns 409.
128Body
Generate one or more images from a prompt and optional reference images.
Text prompt for image generation
Requested aspect ratio (e.g. 1:1, 16:9, 9:16)
Number of images to generate
GPT Image aspect preset used to choose a concrete size
GPT Image concrete WxH size
Client-supplied key (≤128 chars); a repeat with the same key returns the original generation without re-charging
128OpenAI image background setting (transparent, opaque, auto)
Image quality setting; per-model (low|medium|high|xhigh|max for GPT Image 2.5, 1K|2K|4K for Gemini). Defaults to the selected model's catalog default.
Image resolution tier when the selected model exposes one (for example 1k or 2k).
Asset id from POST /v1/uploads or a generation output's asset_id. Optional mask image URL for inpainting/editing
AI model identifier (provider specific)
OpenAI moderation setting (auto, low)
Optional negative prompt
OpenAI image output format (png, webp, jpeg)
Project scope for the generated asset (optional)
Asset id from POST /v1/uploads or a generation output's asset_id. List of reference image URLs for image-to-image editing
User-facing aliases for reference images, keyed by reference_images
Show child attributes
Show child attributes
OpenAI image response format (b64_json, url)
Response
Successful Response
One generation. Poll GET /v1/generations/{id} until status is completed or failed.
"6f1c2d3e-9a0b-4c7d-8e1f-2a3b4c5d6e7f"
"seedance-2-5-fal"
pending, completed, failed image, video, audio Credits actually charged; null while pending.
Show child attributes
Show child attributes
Show child attributes
Show child attributes