Skip to content

Image Generation and Editing API ​

Last updated: October 17, 2026 (Asia/Shanghai)

Related: Help Center · LLM API · Video Generation

This guide explains how to use TokenExplore's text-to-image and image editing capabilities. If you only want the model to "look at and understand an image," see LLM API · Multimodal; do not use the endpoints on this page.


1. Choose a Protocol ​

The models TokenExplore currently offers explicitly for image generation are the Gemini image series:

  • gemini-3-pro-image
  • gemini-3.1-flash-image
ProtocolPathNotes
Gemini native (recommended)POST https://ai.afp.net/v1beta/models/{model}:generateContentParameters map most closely to Gemini's image capabilities; suitable for production batches
OpenAI Images-compatiblePOST https://ai.afp.net/v1/images/generations, /v1/images/editsReuse the OpenAI SDK; available models are subject to /v1/models and the "supported endpoints" shown in the console

INFO

Do not assume that gpt-image-*, dall-e-*, or Imagen :predict models are available on the platform. If the console does not list them, do not invent model names to call them. For image generation, prefer the *-image models above.

Auth: for OpenAI paths use Authorization: Bearer sk-xxx; for Gemini native, x-goog-api-key: sk-xxx is recommended (Bearer also works).

Warning

Protect your API key; never put it in frontend code, screenshots, or public repositories.


2. List Models ​

bash
curl "$CIYUAN_BASE_URL/v1/models" \
  -H "Authorization: Bearer $CIYUAN_API_KEY"

Look for gemini-3-pro-image and gemini-3.1-flash-image in the returned list, along with any other models that the console marks as supporting images/generations (if any). For pricing, see the console pricing page.


3. Gemini Native: Text-to-Image ​

bash
curl "$CIYUAN_BASE_URL/v1beta/models/gemini-3-pro-image:generateContent" \
  -H "x-goog-api-key: $CIYUAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "role": "user",
      "parts": [{"text": "An orange cat sitting by the window watching the rain, watercolor style"}]
    }],
    "generationConfig": {
      "responseModalities": ["TEXT", "IMAGE"],
      "imageConfig": {"aspectRatio": "16:9"}
    }
  }'

In the returned candidates[0].content.parts[], the part with inlineData (mimeType + Base64 data) is the image.

python
# pip install -U google-genai
import os
from google import genai
from google.genai import types

client = genai.Client(
    api_key=os.environ["CIYUAN_API_KEY"],
    http_options=types.HttpOptions(base_url=os.environ["CIYUAN_BASE_URL"]),
)

resp = client.models.generate_content(
    model="gemini-3-pro-image",
    contents="An orange cat sitting by the window watching the rain, watercolor style",
    config=types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"]),
)
for part in resp.candidates[0].content.parts:
    if part.inline_data:
        with open("cat.png", "wb") as f:
            f.write(part.inline_data.data)
    elif part.text:
        print(part.text)

Common generationConfig fields (depending on model support):

FieldNotes
responseModalities["TEXT","IMAGE"] is recommended
imageConfig.aspectRatioe.g. 1:1, 16:9, 9:16, 3:4, 4:3
imageConfig.imageSizeSemantic sizes such as 1K, supported by some models
candidateCountNumber of candidates; rely on what is actually returned and iterate over the array

4. Gemini Native: Image Editing / Reference Images ​

Put the reference image (inlineData) and the text instruction in parts at the same time:

bash
IMAGE_BASE64="$(base64 -w0 reference.png 2>/dev/null || base64 < reference.png | tr -d '\n')"

curl "$CIYUAN_BASE_URL/v1beta/models/gemini-3.1-flash-image:generateContent" \
  -H "x-goog-api-key: $CIYUAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"contents\": [{
      \"role\": \"user\",
      \"parts\": [
        {\"inlineData\": {\"mimeType\": \"image/png\", \"data\": \"$IMAGE_BASE64\"}},
        {\"text\": \"Change the background to a snowy scene, keep the subject composition unchanged, and generate a new image; do not copy the reference image as-is\"}
      ]
    }],
    \"generationConfig\": {
      \"responseModalities\": [\"TEXT\", \"IMAGE\"],
      \"imageConfig\": {\"aspectRatio\": \"1:1\"}
    }
  }"

State clearly in the prompt that the model should "generate a new image, not copy the reference as-is" to reduce results that are nearly identical to the reference image.


5. OpenAI Images-Compatible API ​

bash
curl "$CIYUAN_BASE_URL/v1/images/generations" \
  -H "Authorization: Bearer $CIYUAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<a model the console marks as supporting images/generations>",
    "prompt": "An orange cat sitting by the window watching the rain, watercolor style",
    "n": 1,
    "size": "1024x1024",
    "response_format": "b64_json"
  }'
python
from openai import OpenAI
import base64
from pathlib import Path

client = OpenAI(
    api_key="sk-xxxxxxxx",
    base_url="https://ai.afp.net/v1",
)
result = client.images.generate(
    model="<model supporting images/generations>",
    prompt="An orange cat sitting by the window watching the rain, watercolor style",
    size="1024x1024",
    n=1,
    response_format="b64_json",
)
Path("image.png").write_bytes(base64.b64decode(result.data[0].b64_json))

Editing endpoint: POST https://ai.afp.net/v1/images/edits (multipart/form-data or JSON). Use curl -F or a standard multipart library; do not hand-write the Content-Type boundary.

Notes:

  • Generation is synchronous; the result exists only in this response, so save it to disk promptly. If it takes too long, you may get 504 task_timeout.
  • n is the number of output images; image[] in multipart is the input reference image. They mean different things.
  • If you call a Gemini image model through the OpenAI-compatible wrapper, some OpenAI-specific fields (such as certain style values, background=transparent, or moderation set to anything other than auto) may have no effect or return errors—putting style requirements in the prompt is more reliable.
  • You can also call *-image models via /v1/chat/completions, but how images are returned in content (Markdown / Data URL, etc.) depends on the platform version; for batch production, use Gemini native.

6. FAQ for This Page ​

What if no image is returned?
Check whether parts contains inlineData; it may have been filtered by safety policies, or only text was returned. Reduce sensitive or copyright-related wording and retry.

Can I generate multiple images at once?
For OpenAI paths, use n; for Gemini native, use candidateCount. Be sure to iterate over the returned array, not just read the first image.

The edited image looks almost identical to the reference?
State explicitly in the prompt: "regenerate a new image; do not copy the reference image."

Multipart returns "invalid request body" or NextPart: EOF?
This is usually because the boundary/body was mangled by middleware. Use curl -F or the official SDK instead of hand-writing multipart.

Can I use Imagen :predict?
Only if the console and /v1/models actually provide the corresponding model. This guide does not use Imagen as the primary path.

How is billing calculated?
Per call or per specification, subject to console pricing and "Usage Logs"; this guide does not list numbers.


Previous: LLM API · Next: Video Generation