Qwen Image Text-to-Image Quick Start for Generating Images from Prompts

Qwen Image Text-to-Image Quick Start for Generating Images from Prompts

The Qwen Image text-to-image API on Novita AI generates images from text prompts using the 20B Qwen Image model — the same foundation that powers the Qwen Image Edit API for precise editing tasks. This quick start covers the full async workflow: submit a generation request, get a task ID, poll for completion, and retrieve your image URL. The endpoint is POST https://api.novita.ai/v3/async/qwen-image-txt2img.

When to Use This Quick Start

Use this guide when you need to:

  • Generate images from text prompts with high-quality text rendering in English or Chinese via POST /v3/async/qwen-image-txt2img.
  • Build pipelines that create posters, graphic assets, or illustrated content where text legibility inside the image matters.
  • Prototype quickly against a hosted API rather than running the 20B model on local GPU infrastructure.

The Qwen Image model is especially strong at generating images with readable, styled text embedded in the output — think posters, signs, product mockups, and cover graphics. If your use case involves editing an existing image rather than generating from scratch, see the Qwen Image Edit API instead. If you want a full overview of the Qwen Image model capabilities and benchmarks, Novita AI’s Qwen Image launch post covers the architecture and benchmark results in detail.

Step 1: Get Your Novita API Key

Create a Novita AI account and navigate to API key management. Generate a key and store it as an environment variable:

export NOVITA_API_KEY="your_api_key_here"

Keep the key out of client-side code, frontend bundles, and version control.

Step 2: Confirm the Endpoint and Model

ItemValue
Generation endpointPOST https://api.novita.ai/v3/async/qwen-image-txt2img
Result polling endpointGET https://api.novita.ai/v3/async/task-result?task_id=<id>
ModelQwen Image (20B MMDiT)
API docsNovita AI Qwen Image txt2img reference

The API follows a two-step async pattern common to all Novita AI image generation endpoints. The generation call returns only a task_id; you poll the result endpoint separately until the task completes.

Pricing is $0.02 per image, consistent with the Qwen Image Edit endpoint. Verify the current rate on the Novita AI pricing page before building a cost estimate.

Step 3: Send Your First Request

POST to the generation endpoint with a prompt and an optional size:

curl -s -X POST https://api.novita.ai/v3/async/qwen-image-txt2img \
  -H "Authorization: Bearer $NOVITA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A cinematic mountain landscape at sunrise, warm golden light, ultra-detailed, 8K",
    "size": "1024*1024"
  }'

A successful 200 response returns:

{
  "task_id": "abc123..."
}

Save the task_id. You will use it in the next step.

Step 4: Poll for Your Result

GET the task result endpoint with the task_id as a query parameter:

curl -s "https://api.novita.ai/v3/async/task-result?task_id=abc123..." \
  -H "Authorization: Bearer $NOVITA_API_KEY"

The response includes a status field. Keep polling until status is TASK_STATUS_SUCCEED:

{
  "task": {
    "task_id": "abc123...",
    "status": "TASK_STATUS_SUCCEED"
  },
  "images": [
    {
      "image_url": "https://...",
      "image_url_ttl": "3600",
      "image_type": "png"
    }
  ]
}

The image_url is a time-limited URL — the image_url_ttl value (in seconds) tells you how long it stays valid. Download the image promptly or proxy it through your own storage if you need long-term access.

Status values to handle:

StatusMeaning
TASK_STATUS_QUEUEDRequest is queued, not yet started
TASK_STATUS_PROCESSINGGeneration in progress
TASK_STATUS_SUCCEEDImage is ready; read images[0].image_url
TASK_STATUS_FAILEDGeneration failed; check task.reason

Python Example: End-to-End

This script submits a generation request, polls until complete, and prints the image URL.

import os
import time
import requests

API_KEY = os.environ["NOVITA_API_KEY"]
BASE_URL = "https://api.novita.ai"


def generate_image(prompt: str, size: str = "1024*1024") -> str:
    response = requests.post(
        f"{BASE_URL}/v3/async/qwen-image-txt2img",
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        },
        json={"prompt": prompt, "size": size},
    )
    response.raise_for_status()
    return response.json()["task_id"]


def poll_result(task_id: str, interval: float = 2.0, max_attempts: int = 60) -> str:
    for _ in range(max_attempts):
        response = requests.get(
            f"{BASE_URL}/v3/async/task-result",
            headers={"Authorization": f"Bearer {API_KEY}"},
            params={"task_id": task_id},
        )
        response.raise_for_status()
        data = response.json()
        status = data["task"]["status"]

        if status == "TASK_STATUS_SUCCEED":
            return data["images"][0]["image_url"]
        elif status == "TASK_STATUS_FAILED":
            reason = data["task"].get("reason", "unknown")
            raise RuntimeError(f"Generation failed: {reason}")

        time.sleep(interval)

    raise TimeoutError(f"Task {task_id} did not complete after {max_attempts} polls")


if __name__ == "__main__":
    prompt = (
        "A poster reading 'Welcome to Novita AI' in bold neon letters "
        "against a dark city skyline at night, cinematic lighting"
    )
    task_id = generate_image(prompt, size="1024*1024")
    print(f"Task ID: {task_id}")

    image_url = poll_result(task_id)
    print(f"Image URL: {image_url}")

cURL Example

Two-command pattern for the full workflow:

# Step 1: Submit generation request
TASK_ID=$(curl -s -X POST https://api.novita.ai/v3/async/qwen-image-txt2img \
  -H "Authorization: Bearer $NOVITA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A serene Japanese garden with cherry blossoms, koi pond, morning mist, watercolor style",
    "size": "1024*1536"
  }' | python3 -c "import sys,json; print(json.load(sys.stdin)['task_id'])")

echo "Task ID: $TASK_ID"

# Step 2: Poll until complete
while true; do
  STATUS=$(curl -s "https://api.novita.ai/v3/async/task-result?task_id=$TASK_ID" \
    -H "Authorization: Bearer $NOVITA_API_KEY")
  STATE=$(echo $STATUS | python3 -c "import sys,json; print(json.load(sys.stdin)['task']['status'])")
  echo "Status: $STATE"
  if [ "$STATE" = "TASK_STATUS_SUCCEED" ]; then
    echo $STATUS | python3 -c "import sys,json; print(json.load(sys.stdin)['images'][0]['image_url'])"
    break
  elif [ "$STATE" = "TASK_STATUS_FAILED" ]; then
    echo "Generation failed"
    break
  fi
  sleep 2
done

Key Parameters

ParameterTypeRequiredDefaultNotes
promptstringYesText description of the image to generate. Supports English and Chinese.
sizestringNo1024*1024Width × height in pixels, formatted as W*H. Each dimension: 256–1536.

Size options to consider:

Use caseRecommended size
Square (social, profile)1024*1024
Portrait (mobile, poster)1024*1536
Landscape (banner, thumbnail)1536*1024

There is no separate negative_prompt, steps, or cfg_scale parameter on this endpoint — the model handles those decisions internally. Focus your prompt on what the image should contain and its visual style.

What Qwen Image Generates Well

The 20B MMDiT architecture gives Qwen Image a genuine advantage in a few specific areas:

Text in images. Most image generation models struggle with readable text — words blur, letters swap, and multi-line layouts collapse. Qwen Image handles English and Chinese text with noticeably better accuracy. Posters, signs, labels, and captioned graphics are viable use cases rather than a coin-flip.

Semantic consistency. When a prompt describes a scene with multiple elements and specific spatial relationships, Qwen Image tends to honour the layout intent more reliably than smaller or older architectures.

Prompt-following at scale. Long, detailed prompts that describe multiple attributes — scene, lighting, style, color palette, specific objects — produce outputs that reflect the full prompt rather than latching onto one keyword.

Where it is less suited: real-time or interactive generation workflows. The async pattern means there is inherent latency between request and result. If your use case requires sub-second feedback, this endpoint is not the right fit.

Common Errors and Fixes

401 Unauthorized: Check that the Authorization header is formatted as Bearer <key> with a space after Bearer. Verify the key is active in the Novita AI console.

400 Bad Request on size: The size parameter must use * as the separator (e.g., 1024*1024), not x, ×, or a JSON array. Each dimension must be between 256 and 1536.

TASK_STATUS_FAILED with no reason: Usually caused by a prompt that triggers content filtering. Simplify the prompt and retry. Avoid prompts with explicit violence, sexual content, or content that may match safety filters.

Image URL expired (403 or 404 on the URL): The image_url_ttl field tells you how long the URL is valid. Download the image immediately after polling succeeds, or store it in your own object storage.

Slow polling: Generation time varies with server load. Starting poll at 2-second intervals is reasonable. If the task is still TASK_STATUS_QUEUED after 10 seconds, continue polling — queue depth can spike during peak usage.

FAQ

Is there an OpenAI-compatible endpoint for Qwen Image txt2img?

No. The /v3/async/qwen-image-txt2img endpoint uses Novita AI’s native async image API, not the OpenAI image generation format. If you need OpenAI-compatible image generation, Novita AI offers FLUX and SDXL models through compatible endpoints — see the Novita AI docs.

What is the difference between this endpoint and the Qwen Image Edit endpoint?

This endpoint generates images from a text prompt only — no input image is needed. The Qwen Image Edit endpoint takes an existing image plus a text instruction and modifies the image accordingly. Use txt2img when you are creating from scratch; use edit when you need to change something in an existing image.

Does the model support aspect ratios other than square?

Yes. Use the size parameter to set width and height independently anywhere from 256 to 1536 pixels per dimension. Tall ratios (e.g., 1024*1536) work well for portrait content; wide ratios (e.g., 1536*1024) suit banners and thumbnails.

How do I get consistent results across multiple generations?

There is no seed parameter on the txt2img endpoint. Each request produces a different result. If you need reproducible output, save the image URL immediately and store the image in your own storage rather than re-generating.

Can I use this API in a batch job?

Yes. Submit multiple generation requests and collect the task IDs, then poll them in parallel. Each request returns its own task_id, so batch workflows are straightforward — you do not need to wait for one to finish before submitting the next.