Skip to content

Guides

Image generation

Generate images with NoviaHub: gpt-image-2 uses the Images endpoint, Gemini image models use the Gemini or Chat endpoint, and how each is billed.

Image models on NoviaHub come in two kinds, and you call them differently:

Model Endpoint
OpenAI image models such as gpt-image-2 OpenAI Images: POST /v1/images/generations
Gemini image models such as gemini-3.1-flash-image Gemini: POST /v1beta/models/{model}:generateContent, or Chat Completions

Which image models are available and what they cost is listed on Models & Pricing. The two kinds are also billed differently; see “Billing” in each section below.

终端窗口
curl https://noviahub.com/v1/images/generations \
-H "Authorization: Bearer $NOVIAHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "An orange cat sunbathing on a windowsill, watercolour style",
"size": "1024x1024",
"n": 1
}'

Parameters:

  • model: required.
  • prompt: the image description; OpenAI requires it.
  • n: how many images to generate, at most 128; leaving it out or sending 0 means 1 image. More than 128 returns HTTP 400 n must be an integer between 1 and 128.
  • size, quality, background, output_format and similar parameters are passed to the model unchanged; see OpenAI’s documentation for their values.

data in the response is an array with one entry per image. The gpt-image models return images base64-encoded in b64_json, which is what the sample above decodes and saves.

Billing: as of 2026-09-29, gpt-image-2 is billed by tokens on NoviaHub, not per image. The prompt (text input), image input (images you upload for edits) and the generated images (output) each have a price per million tokens, plus cache prices. The upstream reports the output token count for the generated images, and NoviaHub charges by the usage it reports. The prices are on the model’s details page.

gemini-3.1-flash-image can’t be called through /v1/images/generations; that returns HTTP 500 not supported model for image generation, only imagen models are supported. Use one of these two ways instead.

终端窗口
curl "https://noviahub.com/v1beta/models/gemini-3.1-flash-image:generateContent" \
-H "x-goog-api-key: $NOVIAHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"role": "user", "parts": [{"text": "An orange cat sunbathing on a windowsill, watercolour style"}]}],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {"aspectRatio": "16:9", "imageSize": "2K"}
}
}'

The generated image appears in candidates[0].content.parts: in the inlineData part, the data field is the base64-encoded image.

终端窗口
curl https://noviahub.com/v1/chat/completions \
-H "Authorization: Bearer $NOVIAHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.1-flash-image",
"messages": [{"role": "user", "content": "An orange cat sunbathing on a windowsill, watercolour style"}],
"extra_body": {"google": {"image_config": {"aspect_ratio": "16:9", "image_size": "2K"}}}
}'
  • When you call these image models through Chat, NoviaHub asks the model for both text and image output automatically; you don’t need to set anything.
  • Put the aspect ratio and resolution in extra_body.google.image_config, with snake_case keys: aspect_ratio and image_size. camelCase keys (imageConfig, aspectRatio, imageSize) return an error.
  • The image comes back as Markdown in the reply’s content, like ![image](data:image/png;base64,...). The part starting with data: is the image data.

Billing: as of 2026-09-29, gemini-3.1-flash-image is billed per generated image, with a price per image in four resolution tiers: 0.5K, 1K, 2K and 4K.

  • The native Gemini API uses generationConfig.imageConfig.imageSize;
  • Chat uses extra_body.google.image_config.image_size;
  • 512 (or 512px) is the 0.5K tier, and 2K and 4K are the 2K and 4K tiers (either case); no value or any other value is billed as 1K.

Each tier’s price is on the model’s details page. The image count is the number of final images in the response; draft images produced while the model thinks don’t count. If a request succeeds but returns no image, it is billed as 1 image.