Image Generation
Generate images from text prompts using AI models through the Bulutistan LLMaaS Platform API.
Overview
The Bulutistan LLMaaS Platform provides an OpenAI-compatible image generation endpoint, allowing you to generate images from text descriptions using deployed image models. If you already use the OpenAI SDK for image generation, switching to Bulutistan LLMaaS requires only changing the base_url -- no other code changes needed.
Key features:
- OpenAI SDK compatible -- use the official Python or Node.js SDK
- Flexible output formats -- receive images as base64-encoded data or URLs
- Fine-grained control -- adjust inference steps, guidance scale, seeds, and negative prompts
- Batch generation -- generate up to 10 images in a single request
Quick Start
Python
from openai import OpenAI
client = OpenAI(
base_url="https://api.bulutistan.ai/v1",
api_key="sk-proj-your-api-key"
)
response = client.images.generate(
model="your-image-model",
prompt="A sunset over mountains",
n=1,
size="1024x1024"
)
print(response.data[0].b64_json)
Node.js
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'sk-proj-your-api-key',
baseURL: 'https://api.bulutistan.ai/v1'
});
const response = await client.images.generate({
model: 'your-image-model',
prompt: 'A sunset over mountains',
n: 1,
size: '1024x1024'
});
console.log(response.data[0].b64_json);
API Reference
Endpoint
POST /v1/images/generations
POST /api/v1/images/generations
Both paths are supported. Use /v1/images/generations when setting the SDK base_url to https://api.bulutistan.ai/v1. Use the full /api/v1/images/generations path for direct HTTP requests.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | The model identifier for the image generation model to use. |
prompt | string | Yes | A text description of the desired image. |
n | integer | No | Number of images to generate (1-10). Default: 1. |
size | string | No | Image dimensions. Default: 1024x1024. |
quality | string | No | Generation quality: standard or hd. |
style | string | No | Image style: vivid or natural. |
response_format | string | No | Output format: url or b64_json. Default: b64_json. |
num_inference_steps | integer | No | Number of denoising steps (1-200). Higher values produce better quality but take longer. |
guidance_scale | float | No | Classifier-free guidance scale (0-20). Higher values follow the prompt more closely. |
seed | integer | No | Random seed for reproducible generation. |
negative_prompt | string | No | Text description of what to exclude from the generated image. |
Request Body Example
{
"model": "your-image-model",
"prompt": "A photorealistic landscape of snow-capped mountains at golden hour",
"n": 2,
"size": "1024x1024",
"quality": "hd",
"response_format": "b64_json",
"num_inference_steps": 30,
"guidance_scale": 7.5,
"seed": 42,
"negative_prompt": "blurry, low quality, distorted"
}
Response Format
The API returns a JSON object containing a list of generated images and a creation timestamp.
Response Structure
{
"created": 1704067200,
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUgAA...",
"revised_prompt": "A photorealistic landscape..."
}
]
}
When response_format is set to url, each item contains a url field instead of b64_json. The platform does not host generated files — the url format is only returned when the upstream provider serving the model itself returns URLs, and the value is passed through verbatim (so it points at the provider's own host):
{
"created": 1704067200,
"data": [
{
"url": "https://images.provider.example/generated/img-abc123.png",
"revised_prompt": "A photorealistic landscape..."
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
created | integer | Unix timestamp of when the response was created. |
data | array | List of generated image objects. |
data[].b64_json | string | Base64-encoded image data (when response_format is b64_json). |
data[].url | string | URL to the generated image on the upstream provider's host (when response_format is url and the provider returns URLs). |
data[].revised_prompt | string | The prompt that was used for generation (may be revised from the original). |
cURL Example
curl -X POST https://api.bulutistan.ai/v1/images/generations \
-H "Authorization: Bearer sk-proj-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "your-image-model",
"prompt": "A sunset over mountains",
"n": 1,
"size": "1024x1024"
}'
With Advanced Parameters
curl -X POST https://api.bulutistan.ai/v1/images/generations \
-H "Authorization: Bearer sk-proj-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "your-image-model",
"prompt": "A futuristic city skyline at night with neon lights",
"n": 1,
"size": "1024x1024",
"num_inference_steps": 50,
"guidance_scale": 7.5,
"seed": 12345,
"negative_prompt": "blurry, low resolution"
}'
Saving the Output
# Save base64 response as an image file
curl -s -X POST https://api.bulutistan.ai/v1/images/generations \
-H "Authorization: Bearer sk-proj-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "your-image-model",
"prompt": "A sunset over mountains",
"n": 1,
"size": "1024x1024"
}' | python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
img = base64.b64decode(data['data'][0]['b64_json'])
with open('output.png', 'wb') as f:
f.write(img)
print('Saved to output.png')
"
Node.js Example
Basic Generation with Error Handling
import OpenAI from 'openai';
import fs from 'fs';
const client = new OpenAI({
apiKey: 'sk-proj-your-api-key',
baseURL: 'https://api.bulutistan.ai/v1'
});
async function generateImage(prompt, options = {}) {
try {
const response = await client.images.generate({
model: options.model || 'your-image-model',
prompt,
n: options.n || 1,
size: options.size || '1024x1024',
response_format: options.responseFormat || 'b64_json',
...options.extra
});
return response.data;
} catch (error) {
if (error instanceof OpenAI.AuthenticationError) {
console.error('Invalid API key. Check your credentials.');
throw error;
}
if (error instanceof OpenAI.BadRequestError) {
console.error('Invalid request:', error.message);
throw error;
}
if (error instanceof OpenAI.RateLimitError) {
console.error('Rate limit exceeded. Please try again later.');
throw error;
}
console.error('Image generation failed:', error.message);
throw error;
}
}
// Generate and save to file
async function generateAndSave(prompt, outputPath) {
const images = await generateImage(prompt);
const buffer = Buffer.from(images[0].b64_json, 'base64');
fs.writeFileSync(outputPath, buffer);
console.log(`Image saved to ${outputPath}`);
}
generateAndSave('A sunset over mountains', 'output.png');
Batch Generation
async function generateBatch(prompts, options = {}) {
const results = await Promise.all(
prompts.map(prompt => generateImage(prompt, options))
);
return results.flat();
}
// Generate multiple images from different prompts
const prompts = [
'A serene mountain lake at dawn',
'A bustling cyberpunk street market',
'An ancient library filled with glowing books'
];
const images = await generateBatch(prompts);
console.log(`Generated ${images.length} images`);
Error Handling
Common Errors
The gateway itself validates authentication and that the requested model exists and supports image generation. Parameter-range validation (steps, guidance scale, sizes, etc.) is model-dependent — parameters are forwarded to the model as-is, and out-of-range values are rejected by the serving engine.
| Status Code | Error | Cause | Resolution |
|---|---|---|---|
| 400 | Bad Request | Malformed request body, or a parameter rejected by the model serving the request. | Check the request parameters against the API reference above. |
| 401 | Unauthorized | Missing or invalid API key. | Verify your API key is correct and active. |
| 404 | Not Found | The specified model does not exist or is not deployed. | Check available models in the Client Portal or via the models endpoint. |
| 413 | Payload Too Large | Prompt text exceeds the maximum allowed length. | Shorten your prompt text. |
| 422 | Unprocessable Entity | A parameter rejected by the model (e.g., n out of range for that model). | Review the parameter constraints in the table above. |
| 429 | Too Many Requests | Rate limit exceeded. | Implement exponential backoff and retry. See the Rate Limiting guide. |
| 500 | Internal Server Error | Server-side issue during generation. | Retry the request. If it persists, contact support. |
Python Error Handling
from openai import (
OpenAI,
APIError,
RateLimitError,
AuthenticationError,
BadRequestError,
NotFoundError
)
import time
client = OpenAI(
api_key="sk-proj-your-api-key",
base_url="https://api.bulutistan.ai/v1"
)
def generate_with_retry(prompt, max_retries=3):
for attempt in range(max_retries):
try:
response = client.images.generate(
model="your-image-model",
prompt=prompt,
n=1,
size="1024x1024"
)
return response.data[0]
except AuthenticationError:
print("Invalid API key. Check your credentials.")
raise
except NotFoundError:
print("Model not found. Verify the model identifier.")
raise
except BadRequestError as e:
print(f"Invalid request: {e.message}")
raise
except RateLimitError:
if attempt == max_retries - 1:
raise
wait = 2 ** attempt
print(f"Rate limited. Retrying in {wait}s...")
time.sleep(wait)
except APIError as e:
if attempt == max_retries - 1:
raise
if e.status_code >= 500:
wait = 2 ** attempt
print(f"Server error. Retrying in {wait}s...")
time.sleep(wait)
else:
raise
image = generate_with_retry("A sunset over mountains")
Playground
Image generation is available directly in the Client Portal Playground. You can experiment with prompts, adjust parameters like inference steps and guidance scale, and preview results -- all without writing any code.
To access it:
- Log in to the Client Portal (see the Playground guide).
- Navigate to Playground from the sidebar.
- Select an image generation model from the model selector.
- Enter your prompt and configure parameters.
- Click Generate to create your image.
The Playground is a great way to test prompts and fine-tune parameters before integrating them into your application.
Rate Limits & Pricing
Standard platform rate limits apply to the image generation endpoint. Image generation requests consume tokens based on the model and output resolution.
- Rate limits are applied per API key. See the Rate Limiting guide for details on limits and headers.
- Pricing varies by model. Check the Models page in the Client Portal for per-model pricing information.
- Usage tracking -- all image generation requests are tracked in your usage dashboard, including token consumption and cost.
For high-volume workloads, consider generating images in batches using the n parameter instead of making separate requests for each image. This reduces overhead and helps you stay within rate limits.