# How to Generate Product Images with GPT-Image2: A Complete Technical Guide

> Learn how to generate product images with GPT-Image2. This guide details the API request process, PostgreSQL credit reservation, and Ciyuan service integration for base64 encoded JPEG output.

- Repository: [苍何/awesome-gpt-image-2](https://github.com/freestylefly/awesome-gpt-image-2)
- Tags: how-to-guide
- Published: 2026-08-30

---

**To generate product images with GPT-Image2, send a POST request to the `/api/generate-image` endpoint with a `prompt` and `caseId`; the system validates authentication, reserves credits via PostgreSQL, calls the Ciyuan upstream service, and returns a base64-encoded JPEG data URI.**

The `freestylefly/awesome-gpt-image-2` repository provides a production-ready React and Node.js stack for creating product images using the GPT-Image2 model. This implementation acts as a sophisticated orchestration layer that manages user sessions, credit balances, and communication with the external Ciyuan image-generation service while enforcing strict validation rules.

## Architecture of the GPT-Image2 Generation Flow

### Frontend Request Initialization

When a user initiates generation, the React frontend in [`src/main.jsx`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/main.jsx) constructs a POST request to the internal `/api/generate-image` endpoint. The payload requires two parameters: `prompt` (the image description) and `caseId` (a numeric identifier for the generation context).

```javascript
const response = await fetch('/api/generate-image', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ prompt, caseId })
});

```

### API Handler and Validation Logic

The core logic resides in [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js), which implements a six-stage pipeline:

1. **Method Validation** – Accepts only `GET` and `POST` requests
2. **Configuration Check** – Verifies `CIYUAN_API_KEY` and Supabase credentials; returns `SERVER_NOT_CONFIGURED` if missing
3. **Authentication** – Uses `getAuthContext` from [`api/_lib/supabase.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js) to extract Supabase sessions; `POST` requires authenticated users while `GET` allows anonymous access
4. **Input Validation** – Enforces non-empty prompts ≤ 6000 characters and finite numeric `caseId` values (returns `INVALID_PROMPT` on failure)
5. **Credit Reservation** – Calls `reserveGeneration` for regular users or `reserveCreditGeneration` for super-admins, both invoking the PostgreSQL function `reserve_generation_usage`
6. **Upstream Generation** – Executes `generateImage(prompt)` to contact `https://ciyuan.today/v1/images/generations` using the `gpt-image-2` model

### Response Handling and Cleanup

The handler returns a structured JSON object containing the generated image:

```json
{
  "ok": true,
  "image": "data:image/jpeg;base64,....",
  "user": { "credits": 47, "tier": "pro" }
}

```

If generation succeeds, `completeGenerationReservation` finalizes the credit deduction. On any failure, `releaseGenerationReservation` immediately returns credits to prevent erroneous billing. Upstream errors such as `UPSTREAM_BUSY` or `GENERATION_FAILED` propagate as descriptive error messages.

## Implementation Examples

### Browser-Based Integration

Use this pattern in React or vanilla JavaScript to request images and render them directly:

```javascript
async function generateProductImage(prompt, caseId) {
  const resp = await fetch('/api/generate-image', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ prompt, caseId })
  });

  const data = await resp.json();
  if (!data.ok) throw new Error(data.error);
  return data.image; // Data-URI ready for <img src=...>
}

// Usage example:
generateProductImage('A sleek smartwatch on a marble table', 42)
  .then(img => document.querySelector('#result').src = img)
  .catch(err => console.error(err));

```

### Testing with cURL

For backend validation or CI/CD pipelines, use cURL to verify the endpoint:

```bash
curl -X POST https://your-site.com/api/generate-image \
  -H "Content-Type: application/json" \
  -d '{"prompt":"A futuristic electric scooter in a neon cityscape","caseId":7}' \
  | jq -r '.image' > result.txt

```

### Server-Side Node.js Consumption

When calling from another Node.js service or serverless function:

```javascript
import fetch from 'node-fetch';

async function requestImage(prompt) {
  const res = await fetch('http://localhost:3000/api/generate-image', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ prompt, caseId: 1 })
  });
  const json = await res.json();
  if (!json.ok) throw new Error(json.error);
  return json.image; // Base64 JPEG data URI
}

```

## Validation Rules and Error Codes

The API enforces strict constraints to prevent abuse and ensure quality:

- **Prompt Length**: Maximum 6000 characters; empty strings rejected with `INVALID_PROMPT`
- **Case ID**: Must be a finite number (not `Infinity`, `NaN`, or non-numeric)
- **Credit Requirements**: Returns HTTP 402 (`CREDITS_REQUIRED`) when users lack sufficient balance
- **Upstream Status**: Returns `UPSTREAM_BUSY` when the Ciyuan service is at capacity

## Key Source Files and Functions

| File | Purpose | Critical Functions |
|------|---------|-------------------|
| [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js) | Core API handler orchestrating the entire flow | `generateImage()`, `reserveGeneration()`, `completeGenerationReservation()` |
| [`src/main.jsx`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/main.jsx) | React UI for prompt submission and image display | Fetch call to `/api/generate-image` |
| [`api/_lib/supabase.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js) | Authentication and session management | `getAuthContext()`, `getProfileById()` |
| [`src/supabaseClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/supabaseClient.js) | Supabase client initialization | Client configuration |
| [`data/style-library.json`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/data/style-library.json) | Prompt templates and style taxonomy | Style definitions and templates |

## Summary

- **Endpoint**: POST to `/api/generate-image` with JSON body containing `prompt` (≤6000 chars) and `caseId` (finite number)
- **Authentication**: Required for POST requests via Supabase session; handled by `getAuthContext` in [`api/_lib/supabase.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js)
- **Credit System**: Uses PostgreSQL function `reserve_generation_usage` with automatic cleanup on failure via `releaseGenerationReservation`
- **Upstream Service**: Communicates with Ciyuan API at `https://ciyuan.today/v1/images/generations` using model `gpt-image-2`
- **Response Format**: Returns base64 JPEG as data URI in `image` field, ready for immediate DOM insertion
- **Error Handling**: Distinguishes between validation errors (`INVALID_PROMPT`), payment issues (`CREDITS_REQUIRED`), and upstream failures (`UPSTREAM_BUSY`)

## Frequently Asked Questions

### What is the maximum prompt length for GPT-Image2?

The API enforces a hard limit of **6000 characters** for the `prompt` field. Requests exceeding this length or containing empty strings return the `INVALID_PROMPT` error code immediately, before consuming any credits or contacting the upstream service.

### How does the credit reservation system work?

When a user initiates generation, the system calls `reserveGeneration` (or `reserveCreditGeneration` for super-admins), which executes the PostgreSQL function `reserve_generation_usage`. This atomically deducts credits from the user's balance and creates a reservation record. If generation succeeds, `completeGenerationReservation` finalizes the transaction; if any error occurs, `releaseGenerationReservation` immediately restores the credits to prevent billing for failed attempts.

### Can I use the API without authentication?

**GET requests** to `/api/generate-image` accept anonymous access according to the `getAuthContext` implementation, but **POST requests require a signed-in Supabase user**. The handler validates the session token and rejects unauthenticated POST attempts, ensuring that only registered users with valid credit balances can consume generation resources.

### What image format does the API return?

The endpoint returns a **base64-encoded JPEG** formatted as a data URI (`data:image/jpeg;base64,...`). This format allows immediate rendering in HTML `<img>` tags without additional processing or temporary file storage. The raw base64 string is available in the `b64_json` field of the upstream Ciyuan response and passed through to the client in the `image` property.