Perlu dipahami bahwa image understanding dan image generation adalah dua alur yang berbeda:
POST /v1/chat/completions + image_url.POST /v1/chat/completions + modalities.Halaman ini membahas secara khusus alur image generation bergaya OpenRouter melalui Lunos.
Pilih model yang memiliki "image" di dalam properti outputModalities.
GET /v1/models)Gunakan parameter filter output secara langsung:
curl -s "https://api.lunos.tech/v1/models?output=image"
Anda juga bisa menggabungkan beberapa filter sekaligus, misalnya untuk mencari model yang mendukung input teks dengan output gambar:
curl -s "https://api.lunos.tech/v1/models?input=text&output=image"
Buka halaman Daftar Model, lalu cari model yang memiliki kemampuan output gambar.
Gunakan endpoint Chat Completions dengan menambahkan parameter modalities:
modalities: ["image", "text"]modalities: ["image"]Endpoint:
POST /v1/chat/completions
curl -X POST "https://api.lunos.tech/v1/chat/completions" \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openrouter/google/gemini-2.5-flash-image",
"messages": [
{
"role": "user",
"content": "Generate a beautiful sunset over mountains"
}
],
"modalities": ["image", "text"],
"stream": false
}'
import requests
payload = {
"model": "openrouter/google/gemini-2.5-flash-image",
"messages": [
{"role": "user", "content": "Generate a beautiful sunset over mountains"}
],
"modalities": ["image", "text"],
"stream": False,
}
response = requests.post(
"https://api.lunos.tech/v1/chat/completions",
headers={
"Authorization": "Bearer YOUR_SECRET_KEY",
"Content-Type": "application/json",
},
json=payload,
)
result = response.json()
print(result)
const response = await fetch("https://api.lunos.tech/v1/chat/completions", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_SECRET_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "openrouter/google/gemini-2.5-flash-image",
messages: [{ role: "user", content: "Generate a beautiful sunset over mountains" }],
modalities: ["image", "text"],
stream: false,
}),
});
const result = await response.json();
console.log(result);
Beberapa model mendukung pengaturan tambahan melalui parameter image_config.
image_config.aspect_ratio)Nilai yang umum tersedia:
1:1 (default)2:3, 3:2, 3:4, 4:3, 4:5, 5:49:16, 16:9, 21:9Beberapa model juga mendukung rasio yang lebih ekstrem seperti 1:4, 4:1, 1:8, 8:1.
image_config.image_size)Nilai yang umum tersedia:
1K (default)2K4KBeberapa model juga menyediakan opsi 0.5K.
curl -X POST "https://api.lunos.tech/v1/chat/completions" \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openrouter/google/gemini-3-pro-image-preview",
"messages": [
{
"role": "user",
"content": "Create a high-end restaurant scene with a futuristic nano banana dish"
}
],
"modalities": ["image", "text"],
"image_config": {
"aspect_ratio": "16:9",
"image_size": "4K"
}
}'
import requests
payload = {
"model": "openrouter/google/gemini-3-pro-image-preview",
"messages": [
{"role": "user", "content": "Create a high-end restaurant scene with a futuristic nano banana dish"}
],
"modalities": ["image", "text"],
"image_config": {
"aspect_ratio": "16:9",
"image_size": "4K",
},
}
response = requests.post(
"https://api.lunos.tech/v1/chat/completions",
headers={
"Authorization": "Bearer YOUR_SECRET_KEY",
"Content-Type": "application/json",
},
json=payload,
)
print(response.json())
const response = await fetch("https://api.lunos.tech/v1/chat/completions", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_SECRET_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "openrouter/google/gemini-3-pro-image-preview",
messages: [
{
role: "user",
content: "Create a high-end restaurant scene with a futuristic nano banana dish",
},
],
modalities: ["image", "text"],
image_config: {
aspect_ratio: "16:9",
image_size: "4K",
},
}),
});
console.log(await response.json());
Untuk model dari Sourceful, terdapat beberapa opsi lanjutan tambahan yang mungkin tersedia:
image_config.font_inputs — untuk merender teks menggunakan font kustom.image_config.super_resolution_references — untuk meningkatkan kualitas gambar berbasis referensi.Ketersediaan opsi ini bergantung pada provider dan model, serta mungkin menambah biaya penggunaan.
Anda dapat menggunakan mode streaming dan membaca chunk data gambar dari properti choices[].delta.images.
curl -N -X POST "https://api.lunos.tech/v1/chat/completions" \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openrouter/google/gemini-2.5-flash-image",
"messages": [{"role": "user", "content": "Create an image of a futuristic city"}],
"modalities": ["image", "text"],
"stream": true
}'
import json
import requests
payload = {
"model": "openrouter/google/gemini-2.5-flash-image",
"messages": [{"role": "user", "content": "Create an image of a futuristic city"}],
"modalities": ["image", "text"],
"stream": True,
}
response = requests.post(
"https://api.lunos.tech/v1/chat/completions",
headers={
"Authorization": "Bearer YOUR_SECRET_KEY",
"Content-Type": "application/json",
},
json=payload,
stream=True,
)
for line in response.iter_lines():
if not line:
continue
data_line = line.decode("utf-8")
if not data_line.startswith("data: "):
continue
data = data_line[6:]
if data == "[DONE]":
break
try:
chunk = json.loads(data)
images = (chunk.get("choices", [{}])[0].get("delta", {}) or {}).get("images", [])
for image in images:
print(image.get("image_url", {}).get("url", "")[:50])
except json.JSONDecodeError:
pass
const response = await fetch("https://api.lunos.tech/v1/chat/completions", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_SECRET_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "openrouter/google/gemini-2.5-flash-image",
messages: [{ role: "user", content: "Create an image of a futuristic city" }],
modalities: ["image", "text"],
stream: true,
}),
});
const reader = response.body?.getReader();
const decoder = new TextDecoder();
if (reader) {
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
for (const line of chunk.split("\n")) {
if (!line.startsWith("data: ")) continue;
const data = line.slice(6);
if (data === "[DONE]") continue;
try {
const parsed = JSON.parse(data);
const images = parsed?.choices?.[0]?.delta?.images ?? [];
images.forEach((img: any) => console.log(img?.image_url?.url?.slice(0, 50)));
} catch {}
}
}
}
Gambar hasil generasi biasanya akan muncul di dalam properti choices[].message.images:
{
"choices": [
{
"message": {
"role": "assistant",
"content": "I generated an image for you.",
"images": [
{
"type": "image_url",
"image_url": {
"url": "data:image/png;base64,iVBORw0KGgoAAA..."
}
}
]
}
}
]
}
"image" di properti outputModalities.modalities sudah diatur dengan benar (["image"] atau ["image", "text"]).modalities sudah disertakan dan diisi dengan benar.GET /v1/models.image_size jika resolusi tinggi tidak diperlukan.outputModalities pada GET /v1/models untuk menemukan model yang mampu menghasilkan gambar.Tidak ada judul di halaman ini.
