Generate an image (native Gemini, non-streaming)
curl --request POST \
--url https://api.hairoute.ai/v1/models/{model}:generateContent \
--header 'Content-Type: application/json' \
--header 'x-goog-api-key: <x-goog-api-key>' \
--data '
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Draw an orange cat"
}
]
}
],
"generationConfig": {
"responseModalities": [
"TEXT",
"IMAGE"
],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}
'import requests
url = "https://api.hairoute.ai/v1/models/{model}:generateContent"
payload = {
"contents": [
{
"role": "user",
"parts": [{ "text": "Draw an orange cat" }]
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}
headers = {
"x-goog-api-key": "<x-goog-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-goog-api-key': '<x-goog-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
contents: [{role: 'user', parts: [{text: 'Draw an orange cat'}]}],
generationConfig: {
responseModalities: ['TEXT', 'IMAGE'],
imageConfig: {aspectRatio: '1:1', imageSize: '1K'}
}
})
};
fetch('https://api.hairoute.ai/v1/models/{model}:generateContent', 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.hairoute.ai/v1/models/{model}:generateContent",
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([
'contents' => [
[
'role' => 'user',
'parts' => [
[
'text' => 'Draw an orange cat'
]
]
]
],
'generationConfig' => [
'responseModalities' => [
'TEXT',
'IMAGE'
],
'imageConfig' => [
'aspectRatio' => '1:1',
'imageSize' => '1K'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-goog-api-key: <x-goog-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.hairoute.ai/v1/models/{model}:generateContent"
payload := strings.NewReader("{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"Draw an orange cat\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-goog-api-key", "<x-goog-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.hairoute.ai/v1/models/{model}:generateContent")
.header("x-goog-api-key", "<x-goog-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"Draw an orange cat\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hairoute.ai/v1/models/{model}:generateContent")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-goog-api-key"] = '<x-goog-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"Draw an orange cat\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"inlineData": {
"mimeType": "image/png",
"data": "<BASE64_IMAGE_DATA>"
}
}
]
},
"finishReason": "STOP"
}
],
"usageMetadata": {
"totalTokenCount": 1302
}
}{
"error": {
"code": 123,
"message": "<string>",
"status": "<string>"
}
}Images
Gemini native image generation
Generate or edit images with the native Gemini generateContent endpoint, for Google/Gemini image models only
POST
/
v1
/
models
/
{model}
:generateContent
Generate an image (native Gemini, non-streaming)
curl --request POST \
--url https://api.hairoute.ai/v1/models/{model}:generateContent \
--header 'Content-Type: application/json' \
--header 'x-goog-api-key: <x-goog-api-key>' \
--data '
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Draw an orange cat"
}
]
}
],
"generationConfig": {
"responseModalities": [
"TEXT",
"IMAGE"
],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}
'import requests
url = "https://api.hairoute.ai/v1/models/{model}:generateContent"
payload = {
"contents": [
{
"role": "user",
"parts": [{ "text": "Draw an orange cat" }]
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}
headers = {
"x-goog-api-key": "<x-goog-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-goog-api-key': '<x-goog-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
contents: [{role: 'user', parts: [{text: 'Draw an orange cat'}]}],
generationConfig: {
responseModalities: ['TEXT', 'IMAGE'],
imageConfig: {aspectRatio: '1:1', imageSize: '1K'}
}
})
};
fetch('https://api.hairoute.ai/v1/models/{model}:generateContent', 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.hairoute.ai/v1/models/{model}:generateContent",
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([
'contents' => [
[
'role' => 'user',
'parts' => [
[
'text' => 'Draw an orange cat'
]
]
]
],
'generationConfig' => [
'responseModalities' => [
'TEXT',
'IMAGE'
],
'imageConfig' => [
'aspectRatio' => '1:1',
'imageSize' => '1K'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-goog-api-key: <x-goog-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.hairoute.ai/v1/models/{model}:generateContent"
payload := strings.NewReader("{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"Draw an orange cat\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-goog-api-key", "<x-goog-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.hairoute.ai/v1/models/{model}:generateContent")
.header("x-goog-api-key", "<x-goog-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"Draw an orange cat\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hairoute.ai/v1/models/{model}:generateContent")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-goog-api-key"] = '<x-goog-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"Draw an orange cat\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"inlineData": {
"mimeType": "image/png",
"data": "<BASE64_IMAGE_DATA>"
}
}
]
},
"finishReason": "STOP"
}
],
"usageMetadata": {
"totalTokenCount": 1302
}
}{
"error": {
"code": 123,
"message": "<string>",
"status": "<string>"
}
}Generate images with the native Gemini
On success, the image is returned in
Decode
This endpoint uses native
For a real request, do not reconstruct or trim the prior
generateContent request and response format. For image models, this endpoint is supported only for Google/Gemini image models. Use the OpenAI image generation endpoint or a model-specific endpoint for Seedream, GPT Image, and other image models. Native calls for Gemini chat models are outside the scope of this image reference.
Features
- Generate images using native Gemini
generateContentrequest and response formats, not OpenAI Images formats - Generate from text, edit one image, combine multiple references, or continue editing across turns
- Set model-supported aspect ratios and output tiers with
generationConfig.imageConfig - Receive text and Base64 images in
candidates[].content.parts[]; use the streaming endpoint for SSE
Authentication
POST https://api.hairoute.ai/v1/models/{model}:generateContent
Replace {model} with an available Google/Gemini image model from the model list. Do not put model in the request body. Pass your HaiRoute API key in x-goog-api-key: YOUR_API_KEY, or use Authorization: Bearer YOUR_API_KEY. Do not substitute a Google API key for your HaiRoute key.
Supported image models
This endpoint is only for Google/Gemini image models.| Model identifier | Model type | Description |
|---|---|---|
gemini-3.1-flash-lite-image | Image generation and editing | Gemini 3.1 Flash Lite Image; configured output tier: 1K. |
gemini-3.1-flash-image | Image generation and editing | Gemini 3.1 Flash Image; configured output tiers: 512 (about 0.5K), 1K, 2K, 4K. |
gemini-3-pro-image | Image generation and editing | Gemini 3 Pro Image; configured output tiers: 1K, 2K, 4K. |
Quick example
curl -X POST 'https://api.hairoute.ai/v1/models/YOUR_GEMINI_IMAGE_MODEL:generateContent' \
-H 'x-goog-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"contents": [{"role": "user", "parts": [{"text": "An orange cat wearing an astronaut helmet floating in space"}]}],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {"aspectRatio": "1:1", "imageSize": "1K"}
}
}'
candidates[].content.parts[].inlineData, with a mimeType and Base64-encoded data. Any accompanying text appears as a text part in the same parts array. The Base64 value below is a placeholder, not an actual image:
{
"candidates": [{
"content": {"role": "model", "parts": [
{"text": "Here is your image:"},
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_IMAGE_DATA>"}}
]},
"finishReason": "STOP"
}],
"usageMetadata": {"promptTokenCount": 12, "candidatesTokenCount": 1290, "totalTokenCount": 1302}
}
inlineData.data to bytes and save them using the supplied mimeType. The response is not an OpenAI Images data[].url response. Usage, candidates, and optional fields vary by model and request.
Key parameters
| Field | Description |
|---|---|
contents | Required. An array of messages. For text-to-image, use role: "user" and parts: [{"text": "..."}]. |
contents[].parts[].inlineData | Optional image input for editing or multiple-reference requests. Provide the image MIME type in mimeType and raw Base64 data without a data URI prefix in data. |
generationConfig.responseModalities | Use ["TEXT", "IMAGE"] for image output; text may accompany the image. |
generationConfig.imageConfig.aspectRatio | Optional aspect ratio, such as 1:1 or 16:9; available values depend on the selected model. |
generationConfig.imageConfig.imageSize | Optional size tier, such as 1K, 2K, or 4K; availability depends on the selected model. |
systemInstruction | Optional native Gemini instruction with the same structure as one contents message. |
generationConfig.imageConfig, not OpenAI Images parameters such as size, quality, or response_format. Supported aspect ratios and sizes depend on model configuration.
Generation modes
These examples show request bodies only. All four modes use this page’s endpoint and authentication; no separatemode parameter is needed. Replace every Base64 placeholder with actual raw Base64 image data.
Text-to-image
Send a text prompt without an input image; the Quick example above is ready to adapt. Local changes and style adjustments are prompt instructions, not separate API parameters.Single-image editing
Put one image and an editing instruction in the sameuser message. This example replaces the background; you can also ask to preserve the subject, change an element, or adjust the style.
{
"contents": [{"role": "user", "parts": [
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_INPUT_IMAGE>"}},
{"text": "Replace the background with a sunset beach and keep the subject"}
]}],
"generationConfig": {"responseModalities": ["TEXT", "IMAGE"]}
}
Multiple-reference composition
Put multiple reference images in oneuser message’s parts and describe the role of each image in the text. Input count, size limits, and results depend on the selected model and channel.
{
"contents": [{"role": "user", "parts": [
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_SUBJECT_IMAGE>"}},
{"inlineData": {"mimeType": "image/jpeg", "data": "<BASE64_BACKGROUND_IMAGE>"}},
{"text": "Use the person in the first image as the subject and the scene in the second as the background; make a natural composite"}
]}],
"generationConfig": {"responseModalities": ["TEXT", "IMAGE"]}
}
Multi-turn editing
Send the previoususer request, the actual previous candidates[0].content as a model message, and your new instruction in that order within contents. This body illustrates the structure only:
{
"contents": [
{"role": "user", "parts": [{"text": "Draw an orange cat wearing a scarf"}]},
{"role": "model", "parts": [
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_FROM_PREVIOUS_RESPONSE>"}}
]},
{"role": "user", "parts": [{"text": "Keep the cat and scarf, but replace the background with a snowy landscape"}]}
],
"generationConfig": {"responseModalities": ["TEXT", "IMAGE"]}
}
model content: replay the complete previous candidates[0].content, including any image, text, and thoughtSignature parts if returned. Multiple references and multi-turn results depend on the selected image model.
Troubleshooting
Check the HTTP status and theerror in the response body first. Never paste API keys or complete image Base64 in logs or support requests.
| Symptom | What to check |
|---|---|
| Authentication fails (for example, 401/403) | Use a HaiRoute API key in either x-goog-api-key or Authorization: Bearer; do not use a Google API key here. Check that the key is valid and allowed to access the model. |
| Model not found or unavailable | Check that {model} in the URL is an available Google/Gemini image model in your account’s model list. Do not put the model name in the request body or use a different image model on this endpoint. |
| Invalid request or input image | Check contents[].parts, generationConfig.responseModalities (["TEXT", "IMAGE"] for image output), and the selected model’s supported imageConfig. inlineData.data must be raw Base64 without a data:image/...;base64, prefix; mimeType must match the input image format. |
| Request succeeds but no image appears | Inspect all candidates[].content.parts[].inlineData; the image is not in data[].url. If absent, inspect finishReason, promptFeedback, and returned text before adjusting the prompt or request. HTTP 200 alone does not prove an image was generated. |
| Multi-turn edit fails or ignores earlier output | Replay the prior user message, the complete previous candidates[0].content (including thoughtSignature if returned), and the new user instruction in order; sending only the image Base64 is insufficient. |
Next steps
- See OpenAI image generation for other image models
Headers
HaiRoute API key for the native request. Alternatively, use Authorization: Bearer YOUR_API_KEY instead (choose one).
Path Parameters
An available Google/Gemini image model in HaiRoute
Body
application/json
Required native Gemini messages. Use a user text part for text-to-image; add inlineData for image-to-image.
Minimum array length:
1Show child attributes
Show child attributes
Show child attributes
Show child attributes
Native Gemini generation settings; availability depends on the image model.
Show child attributes
Show child attributes
Response
Native Gemini GenerateContentResponse with images in candidates[].content.parts[].inlineData.