How to Generate Product Images with GPT-Image2: A Complete Technical Guide
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 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).
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, which implements a six-stage pipeline:
- Method Validation – Accepts only
GETandPOSTrequests - Configuration Check – Verifies
CIYUAN_API_KEYand Supabase credentials; returnsSERVER_NOT_CONFIGUREDif missing - Authentication – Uses
getAuthContextfromapi/_lib/supabase.jsto extract Supabase sessions;POSTrequires authenticated users whileGETallows anonymous access - Input Validation – Enforces non-empty prompts ≤ 6000 characters and finite numeric
caseIdvalues (returnsINVALID_PROMPTon failure) - Credit Reservation – Calls
reserveGenerationfor regular users orreserveCreditGenerationfor super-admins, both invoking the PostgreSQL functionreserve_generation_usage - Upstream Generation – Executes
generateImage(prompt)to contacthttps://ciyuan.today/v1/images/generationsusing thegpt-image-2model
Response Handling and Cleanup
The handler returns a structured JSON object containing the generated image:
{
"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:
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:
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:
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_BUSYwhen the Ciyuan service is at capacity
Key Source Files and Functions
| File | Purpose | Critical Functions |
|---|---|---|
api/generate-image.js |
Core API handler orchestrating the entire flow | generateImage(), reserveGeneration(), completeGenerationReservation() |
src/main.jsx |
React UI for prompt submission and image display | Fetch call to /api/generate-image |
api/_lib/supabase.js |
Authentication and session management | getAuthContext(), getProfileById() |
src/supabaseClient.js |
Supabase client initialization | Client configuration |
data/style-library.json |
Prompt templates and style taxonomy | Style definitions and templates |
Summary
- Endpoint: POST to
/api/generate-imagewith JSON body containingprompt(≤6000 chars) andcaseId(finite number) - Authentication: Required for POST requests via Supabase session; handled by
getAuthContextinapi/_lib/supabase.js - Credit System: Uses PostgreSQL function
reserve_generation_usagewith automatic cleanup on failure viareleaseGenerationReservation - Upstream Service: Communicates with Ciyuan API at
https://ciyuan.today/v1/images/generationsusing modelgpt-image-2 - Response Format: Returns base64 JPEG as data URI in
imagefield, 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →