Gemini 3.1 Flash Image API
Model gambar gemini-3.1-flash-image (Nano Banana 2) menggunakan protokol native Gemini dan tidak menggunakan endpoint OpenAI Images:
- Base URL:
https://api.teamorouter.com - Endpoint:
POST https://api.teamorouter.com/v1beta/models/{model}:generateContent - Autentikasi:
Authorization: Bearer sk-teamo-xxxxxx
Kueri GET /v1/models terlebih dahulu untuk memastikan model tersedia. Anggap respons langsung sebagai sumber kebenaran untuk model yang tersedia dan perutean.
1. Membuat gambar
curl https://api.teamorouter.com/v1beta/models/gemini-3.1-flash-image:generateContent \
-H "Authorization: Bearer sk-teamo-xxxxxx" \
-H "content-type: application/json" \
-d '{
"contents": [
{"role": "user", "parts": [{"text": "A minimal tech poster, 16:9"}]}
],
"generationConfig": {
"responseModalities": ["IMAGE"],
"imageConfig": {"aspectRatio": "16:9", "imageSize": "2K"}
}
}'
Gambar dikembalikan sebagai Base64 di candidates[0].content.parts[].inlineData:
{
"candidates": [
{
"content": {
"parts": [
{
"inlineData": {
"mimeType": "image/png",
"data": "iVBORw0KGgo..."
}
}
]
}
}
]
}
Telusuri setiap entri parts untuk menemukan inlineData; jangan pernah berasumsi gambar berada di part pertama, dan jangan pernah mencatat payload Base64 lengkap ke log.
2. Parameter permintaan
| Field | Nilai umum | Deskripsi |
|---|---|---|
contents[].role |
user |
Peran pesan |
contents[].parts[].text |
String prompt | Subjek, gaya, komposisi, teks, dan batasan |
contents[].parts[].inlineData |
mimeType + data Base64 |
Gambar sumber saat mengedit |
generationConfig.responseModalities |
["IMAGE"] atau ["TEXT", "IMAGE"] |
Mengembalikan gambar, teks, atau keduanya |
generationConfig.imageConfig.aspectRatio |
1:1, 16:9, 9:16, dan lainnya |
Rasio aspek output |
generationConfig.imageConfig.imageSize |
512, 1K, 2K, 4K |
Resolusi output, default 1K |
Tingkat resolusi
Ukuran di bawah menggunakan 1:1; rasio aspek lain menghasilkan ukuran non-persegi yang sesuai:
imageSize |
Output 1:1 | Token output gambar (perkiraan) | Direkomendasikan untuk |
|---|---|---|---|
512 |
512 × 512 | 747 | Pratinjau, draf, pengujian batch berbiaya rendah |
1K |
1024 × 1024 | 1120 | Tingkat default, unggahan media sosial, foto produk |
2K |
2048 × 2048 | 1680 | Poster, halaman detail, gambar dengan banyak teks |
4K |
4096 × 4096 | 2520 | Pengiriman resolusi tinggi, cetak, pemangkasan lanjutan |
Rasio aspek yang didukung: 1:1, 1:4, 1:8, 2:3, 3:2, 3:4, 4:1, 4:3, 4:5, 5:4, 8:1, 9:16, 16:9, 21:9.
Gunakan nilai huruf besar 1K, 2K, 4K di kode produksi. Gateway menerima 2k huruf kecil saat pengujian, tetapi jangan mengandalkannya.
3. Python
pip install requests
import base64
import os
from pathlib import Path
import requests
BASE_URL = "https://api.teamorouter.com"
API_KEY = os.environ["TEAMO_API_KEY"]
MODEL = "gemini-3.1-flash-image"
response = requests.post(
f"{BASE_URL}/v1beta/models/{MODEL}:generateContent",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"contents": [
{
"role": "user",
"parts": [{"text": "A minimal tech poster, 16:9"}],
}
],
"generationConfig": {
"responseModalities": ["IMAGE"],
"imageConfig": {"aspectRatio": "16:9", "imageSize": "2K"},
},
},
timeout=300,
)
response.raise_for_status()
result = response.json()
parts = result["candidates"][0]["content"]["parts"]
image_part = next(part for part in parts if "inlineData" in part)
image_bytes = base64.b64decode(image_part["inlineData"]["data"])
Path("image.png").write_bytes(image_bytes)
4. JavaScript / TypeScript
Node.js 18+ dapat langsung menggunakan fetch:
import fs from "node:fs";
const baseURL = "https://api.teamorouter.com";
const apiKey = process.env.TEAMO_API_KEY;
const model = "gemini-3.1-flash-image";
const response = await fetch(
`${baseURL}/v1beta/models/${model}:generateContent`,
{
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"content-type": "application/json",
},
body: JSON.stringify({
contents: [
{
role: "user",
parts: [{ text: "A minimal tech poster, 16:9" }],
},
],
generationConfig: {
responseModalities: ["IMAGE"],
imageConfig: { aspectRatio: "16:9", imageSize: "2K" },
},
}),
signal: AbortSignal.timeout(300_000),
},
);
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const result = await response.json();
const parts = result.candidates?.[0]?.content?.parts ?? [];
const image = parts.find((part) => part.inlineData?.data);
if (!image) throw new Error("No image part in the response");
fs.writeFileSync("image.png", Buffer.from(image.inlineData.data, "base64"));
5. Mengedit gambar
Pengeditan menggunakan endpoint yang sama. Kirim instruksi dan gambar sumber Base64 bersama-sama di parts:
{
"contents": [
{
"role": "user",
"parts": [
{"text": "Keep the subject and composition, change the background to a sunset beach, add no text"},
{
"inlineData": {
"mimeType": "image/png",
"data": "<BASE64_IMAGE>"
}
}
]
}
],
"generationConfig": {
"responseModalities": ["IMAGE"],
"imageConfig": {"imageSize": "2K"}
}
}
6. Panduan produksi
- Panggil
/v1/modelssaat startup atau secara berkala, jangan mengandalkan tabel model statis, dan hanya tampilkan model yang ada di daftar langsung. - Pembuatan gambar berjalan lambat; setel timeout klien ke 300 detik.
- Hanya coba ulang respons 429 dan 5xx yang dapat dipulihkan dengan exponential backoff. Respons 400 biasanya menandakan masalah pada permintaan atau perutean, jadi mencoba ulang tidak akan membantu.
- Simpan API key di variabel lingkungan sisi server atau secrets manager. Jangan pernah mengirimkannya ke browser, menyimpannya di database, atau menuliskannya ke log.
- Validasi status HTTP,
candidates,finishReason,inlineData.mimeType, dan hasil dekode Base64. - Batasi konkurensi, resolusi output, jumlah gambar referensi, dan kuota harian.
7. Error umum
401 / autentikasi gagal
Pastikan header-nya Authorization: Bearer sk-teamo-xxxxxx, dengan key yang lengkap dan tanpa spasi berlebih. Jika Anda curiga key bocor, segera hapus key di konsol dan buat yang baru.
400 / format endpoint tidak valid
gemini-3.1-flash-image menggunakan URL native Gemini https://api.teamorouter.com/v1beta/models/{model}:generateContent. Jangan menambahkan awalan /v1 ekstra.
404 atau model tidak ditemukan
Kueri /v1/models terlebih dahulu. Jika model tidak ada di daftar langsung, anggap model tersebut belum diaktifkan di gateway dan hentikan percobaan ulang.
Permintaan berhasil tetapi tidak mengembalikan gambar
Pastikan responseModalities menyertakan IMAGE, telusuri setiap entri parts untuk inlineData, dan periksa finishReason serta informasi pemblokiran keamanan apa pun.