Image Generation
This guide walks you through generating images with the neuroflash API — from checking your quota to generating images and tracking usage.
What you'll build
By the end of this guide, you will:
- Authenticate with the neuroflash API
- Fetch your workspace
- Check your workspace's image generation quota
- List available image models
- Generate an image using the image generation endpoint
- Track usage deducted from your quota
Prerequisites
- A neuroflash account with API access and image generation credits
- Your
client_idandclient_secret(see Authentication)
Step 1: Authenticate
- cURL
- Python
- Node.js
- Go
curl -X POST https://id.neuroflash.com/oauth/v2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=openid"
import requests
BASE_URL = "https://app.neuroflash.com/api"
token = requests.post(
"https://id.neuroflash.com/oauth/v2/token",
data={
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"scope": "openid",
},
).json()["access_token"]
headers = {"Authorization": f"Bearer {token}"}
const BASE_URL = "https://app.neuroflash.com/api";
const { access_token } = await fetch(
"https://id.neuroflash.com/oauth/v2/token",
{
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: "YOUR_CLIENT_ID",
client_secret: "YOUR_CLIENT_SECRET",
scope: "openid",
}),
}
).then((r) => r.json());
const headers = { Authorization: `Bearer ${access_token}` };
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
)
const baseURL = "https://app.neuroflash.com/api"
func main() {
data := url.Values{
"grant_type": {"client_credentials"},
"client_id": {"YOUR_CLIENT_ID"},
"client_secret": {"YOUR_CLIENT_SECRET"},
"scope": {"openid"},
}
resp, _ := http.Post(
"https://id.neuroflash.com/oauth/v2/token",
"application/x-www-form-urlencoded",
strings.NewReader(data.Encode()),
)
defer resp.Body.Close()
var authResult struct {
AccessToken string `json:"access_token"`
}
json.NewDecoder(resp.Body).Decode(&authResult)
token := authResult.AccessToken
}
Step 2: Get Your Workspace
Fetch your available workspaces and select the first one. The workspace ID is required for quota and usage calls:
- cURL
- Python
- Node.js
- Go
curl "https://app.neuroflash.com/api/workspace-service/v1/workspaces" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
workspaces = requests.get(
f"{BASE_URL}/workspace-service/v1/workspaces",
headers=headers,
).json()
workspace_id = workspaces["_embedded"]["workspaces"][0]["id"]
headers["x-workspace-id"] = workspace_id
print(f"Using workspace: {workspace_id}")
const workspaces = await fetch(
`${BASE_URL}/workspace-service/v1/workspaces`,
{ headers }
).then((r) => r.json());
const workspaceId = workspaces._embedded.workspaces[0].id;
headers["x-workspace-id"] = workspaceId;
console.log(`Using workspace: ${workspaceId}`);
req, _ := http.NewRequest("GET", baseURL+"/workspace-service/v1/workspaces", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var wsResult struct {
Embedded struct {
Workspaces []struct {
ID string `json:"id"`
} `json:"workspaces"`
} `json:"_embedded"`
}
json.NewDecoder(resp.Body).Decode(&wsResult)
workspaceID := wsResult.Embedded.Workspaces[0].ID
fmt.Printf("Using workspace: %s\n", workspaceID)
Step 3: Check Your Quota
Before generating images, check how many credits you have available:
- cURL
- Python
- Node.js
- Go
curl "https://app.neuroflash.com/api/usage-service/v1/workspaces/{workspace_id}/quotas?usageTypeKey=images" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
quotas = requests.get(
f"{BASE_URL}/usage-service/v1/workspaces/{workspace_id}/quotas",
headers=headers,
params={"usageTypeKey": "images"},
).json()
image_quota = quotas["data"][0]
print(f"Available: {image_quota['availableAmount']} images")
print(f"Used: {image_quota['usedAmount']} images")
print(f"Limit: {image_quota['limitAmount']} images")
const quotas = await fetch(
`${BASE_URL}/usage-service/v1/workspaces/${workspaceId}/quotas?usageTypeKey=images`,
{ headers }
).then((r) => r.json());
const imageQuota = quotas.data[0];
console.log(`Available: ${imageQuota.availableAmount} images`);
console.log(`Used: ${imageQuota.usedAmount} images`);
console.log(`Limit: ${imageQuota.limitAmount} images`);
quotaURL := fmt.Sprintf("%s/usage-service/v1/workspaces/%s/quotas?usageTypeKey=images", baseURL, workspaceID)
req, _ := http.NewRequest("GET", quotaURL, nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var quotas struct {
Data []struct {
AvailableAmount int `json:"availableAmount"`
UsedAmount int `json:"usedAmount"`
LimitAmount int `json:"limitAmount"`
} `json:"data"`
}
json.NewDecoder(resp.Body).Decode("as)
q := quotas.Data[0]
fmt.Printf("Available: %d images\n", q.AvailableAmount)
fmt.Printf("Used: %d images\n", q.UsedAmount)
fmt.Printf("Limit: %d images\n", q.LimitAmount)
Response:
{
"data": [
{
"id": "quota-abc-123",
"workspaceId": "your-workspace-id",
"usageTypeKey": "images",
"bonusAmount": 0,
"spilloverAmount": 0,
"usedAmount": 12,
"usedAmountDaily": 3,
"availableAmount": 88,
"limitAmount": 100,
"limitAmountDaily": 50,
"fairUseLimitReached": false
}
],
"page": {
"size": 20,
"totalElements": 1,
"totalPages": 1,
"currentPage": 1
}
}
Step 4: List Image Models
Fetch the available image generation models to see which ones you can use:
- cURL
- Python
- Node.js
- Go
curl "https://app.neuroflash.com/api/ds-prototypes/image_generation/models" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "x-workspace-id: YOUR_WORKSPACE_ID"
models = requests.get(
f"{BASE_URL}/ds-prototypes/image_generation/models",
headers=headers,
).json()
for model in models:
print(f"{model['id']}: {model['name']} — {model['description']}")
print(f" Capabilities: {', '.join(model['capabilities'])}")
const models = await fetch(
`${BASE_URL}/ds-prototypes/image_generation/models`,
{ headers }
).then((r) => r.json());
for (const model of models) {
console.log(`${model.id}: ${model.name} — ${model.description}`);
console.log(` Capabilities: ${model.capabilities.join(", ")}`);
}
req, _ := http.NewRequest("GET", baseURL+"/ds-prototypes/image_generation/models", nil)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("x-workspace-id", workspaceID)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var models []struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Capabilities []string `json:"capabilities"`
}
json.NewDecoder(resp.Body).Decode(&models)
for _, m := range models {
fmt.Printf("%s: %s — %s\n", m.ID, m.Name, m.Description)
}
Response:
[
{
"id": "nano-banana-2",
"name": "Nano Banana 2",
"provider": "fal.ai",
"description": "Fast and efficient image generation model",
"capabilities": ["text2image", "image2image"],
"max_images": 4,
"aspect_ratios": ["21:9", "16:9", "3:2", "4:3", "5:4", "1:1", "4:5", "3:4", "2:3", "9:16"],
"output_formats": ["jpeg", "png", "webp"],
"allowed": true,
"order": 1
}
]
Step 5: Generate an Image
Use the image generation endpoint with a text prompt:
- cURL
- Python
- Node.js
- Go
curl -X POST "https://app.neuroflash.com/api/ds-prototypes/image_generation/" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "x-workspace-id: YOUR_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A professional hero image for a blog post about sustainable technology. Modern, clean design with green and blue tones.",
"model": "nano-banana-2",
"num_images": 1,
"aspect_ratio": "16:9",
"output_format": "png"
}'
result = requests.post(
f"{BASE_URL}/ds-prototypes/image_generation/",
headers=headers,
json={
"prompt": "A professional hero image for a blog post about sustainable technology. Modern, clean design with green and blue tones.",
"model": "nano-banana-2",
"num_images": 1,
"aspect_ratio": "16:9",
"output_format": "png",
},
).json()
for image in result["images"]:
print(f"Image URL: {image['url']}")
print(f"Size: {image['width']}x{image['height']}")
const result = await fetch(
`${BASE_URL}/ds-prototypes/image_generation/`,
{
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({
prompt:
"A professional hero image for a blog post about sustainable technology. Modern, clean design with green and blue tones.",
model: "nano-banana-2",
num_images: 1,
aspect_ratio: "16:9",
output_format: "png",
}),
}
).then((r) => r.json());
for (const image of result.images) {
console.log(`Image URL: ${image.url}`);
console.log(`Size: ${image.width}x${image.height}`);
}
body, _ := json.Marshal(map[string]any{
"prompt": "A professional hero image for a blog post about sustainable technology. Modern, clean design with green and blue tones.",
"model": "nano-banana-2",
"num_images": 1,
"aspect_ratio": "16:9",
"output_format": "png",
})
req, _ := http.NewRequest("POST", baseURL+"/ds-prototypes/image_generation/", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("x-workspace-id", workspaceID)
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var result struct {
Images []struct {
URL string `json:"url"`
Width int `json:"width"`
Height int `json:"height"`
} `json:"images"`
Prompt string `json:"prompt"`
}
json.NewDecoder(resp.Body).Decode(&result)
for _, img := range result.Images {
fmt.Printf("Image URL: %s\n", img.URL)
fmt.Printf("Size: %dx%d\n", img.Width, img.Height)
}
Response:
{
"images": [
{
"url": "https://storage.example.com/generated/image-abc123.png",
"content_type": "image/png",
"width": 1024,
"height": 576,
"image_id": "3c4ce5dc-00be-4451-9559-0324f9fc4c88"
}
],
"prompt": "A professional hero image for a blog post about sustainable technology...",
"batch_id": "6872b83c-901e-47c5-8b90-96a3d9839d06"
}
Step 6: Track Usage
After image generation, usage is automatically deducted from your workspace quota. You can verify by checking the quota again:
- cURL
- Python
- Node.js
- Go
curl "https://app.neuroflash.com/api/usage-service/v1/workspaces/{workspace_id}/quotas?usageTypeKey=images" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
# Check quota after generation
quotas_after = requests.get(
f"{BASE_URL}/usage-service/v1/workspaces/{workspace_id}/quotas",
headers=headers,
params={"usageTypeKey": "images"},
).json()
image_quota_after = quotas_after["data"][0]
print(f"Available after generation: {image_quota_after['availableAmount']} images")
print(f"Daily usage: {image_quota_after['usedAmountDaily']} images")
const quotasAfter = await fetch(
`${BASE_URL}/usage-service/v1/workspaces/${workspaceId}/quotas?usageTypeKey=images`,
{ headers }
).then((r) => r.json());
const imageQuotaAfter = quotasAfter.data[0];
console.log(`Available after generation: ${imageQuotaAfter.availableAmount} images`);
console.log(`Daily usage: ${imageQuotaAfter.usedAmountDaily} images`);
quotaURL = fmt.Sprintf("%s/usage-service/v1/workspaces/%s/quotas?usageTypeKey=images", baseURL, workspaceID)
req, _ = http.NewRequest("GET", quotaURL, nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ = http.DefaultClient.Do(req)
defer resp.Body.Close()
var quotasAfter struct {
Data []struct {
AvailableAmount int `json:"availableAmount"`
UsedAmountDaily int `json:"usedAmountDaily"`
} `json:"data"`
}
json.NewDecoder(resp.Body).Decode("asAfter)
qa := quotasAfter.Data[0]
fmt.Printf("Available after generation: %d images\n", qa.AvailableAmount)
fmt.Printf("Daily usage: %d images\n", qa.UsedAmountDaily)
Image generation automatically records usage events. The usedAmount on your quota increases with each generation, and usedAmountDaily resets daily.
Step: Edit an existing image (image-to-image)
The /edit endpoint re-generates an image from a source image plus a prompt. The source is
identified by the relative path returned in output_image_url from /history — not an
absolute URL.
Pass the relative path (e.g. /api/ds-prototypes/image_generation/{image_id}/view) from the
/history response. Absolute URLs cause a 500 error because the image service resolves
these paths internally.
Typical flow:
GET /api/ds-prototypes/historyand pick an item- Extract its
output_image_url— a relative path - Pass that path in
image_urlstoPOST /edit
- cURL
- Python
- Node.js
- Go
curl -X POST "https://app.neuroflash.com/api/ds-prototypes/edit" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "x-workspace-id: YOUR_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Make the sky a deep sunset orange",
"image_urls": ["/api/ds-prototypes/image_generation/b64b61f6-a7d2-4fa0-9f88-289dae46c41f/view"]
}'
history = requests.get(f"{BASE_URL}/ds-prototypes/history", headers=headers).json()
source_path = history["items"][0]["output_image_url"]
edited = requests.post(
f"{BASE_URL}/ds-prototypes/edit",
headers={**headers, "x-workspace-id": workspace_id, "Content-Type": "application/json"},
json={"prompt": "Make the sky a deep sunset orange", "image_urls": [source_path]},
).json()
const history = await fetch(`${BASE_URL}/ds-prototypes/history`, { headers })
.then((r) => r.json());
const sourcePath = history.items[0].output_image_url;
const edited = await fetch(`${BASE_URL}/ds-prototypes/edit`, {
method: "POST",
headers: { ...headers, "x-workspace-id": workspaceId, "Content-Type": "application/json" },
body: JSON.stringify({
prompt: "Make the sky a deep sunset orange",
image_urls: [sourcePath],
}),
}).then((r) => r.json());
body, _ := json.Marshal(map[string]any{
"prompt": "Make the sky a deep sunset orange",
"image_urls": []string{sourcePath},
})
req, _ := http.NewRequest("POST", baseURL+"/ds-prototypes/edit", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("x-workspace-id", workspaceID)
req.Header.Set("Content-Type", "application/json")
Step: Delete an image
Use the image_id from the output_image_id field of the history response — not the
batch_id.
- cURL
- Python
- Node.js
- Go
curl -X DELETE "https://app.neuroflash.com/api/ds-prototypes/history/{image_id}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "x-workspace-id: YOUR_WORKSPACE_ID"
image_id = history["items"][0]["output_image_id"]
requests.delete(
f"{BASE_URL}/ds-prototypes/history/{image_id}",
headers={**headers, "x-workspace-id": workspace_id},
)
const imageId = history.items[0].output_image_id;
await fetch(`${BASE_URL}/ds-prototypes/history/${imageId}`, {
method: "DELETE",
headers: { ...headers, "x-workspace-id": workspaceId },
});
req, _ := http.NewRequest("DELETE", baseURL+"/ds-prototypes/history/"+imageID, nil)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("x-workspace-id", workspaceID)
Next Steps
- Learn about usage quotas and limits
- Explore content generation for text generation
- Set up brand voices for consistent visual style prompts