How to Integrate awesome-gpt-image-2 with Other Applications: A Complete API Guide
Integrate awesome-gpt-image-2 by calling its REST endpoint at POST /api/generate-image with a Supabase JWT and a JSON body containing prompt and caseId, which returns a base64-encoded JPEG data URI.
The awesome-gpt-image-2 repository by freestylefly is a full-stack React/Vite application that wraps the GPT-Image-2 model in a clean API layer. Whether you're building a mobile app, a backend service, or a custom dashboard, you can leverage its built-in authentication, credit system, and image generation capabilities without modifying core server code.
Understanding the Core Architecture
The integration surface consists of two primary components:
/api/generate-image– handles image generation, credit reservation, and upstream communication with the Ciyuan service- Supabase authentication layer – manages JWT verification and user profiles
Both are self-contained in the api/ directory and deployable as serverless functions.
API Contract and Endpoints
GET /api/generate-image (Status Check)
This endpoint returns server configuration and anonymous status information without consuming credits.
// Response structure
{
ok: true,
authRequired: boolean,
freeUsed: boolean,
user: <profile|null>
}
The implementation in api/generate-image.js allows anonymous access via allowAnonymous: true for this method.
POST /api/generate-image (Image Generation)
| Parameter | Type | Description |
|---|---|---|
prompt |
string | Maximum 6000 characters (enforced by MAX_PROMPT_LENGTH) |
caseId |
number | Arbitrary numeric identifier for request tracking |
// Success response
{
ok: true,
image: "data:image/jpeg;base64,/9j/4AAQSkZJRg...", // data URI
user: {
creditBalance: 12,
freeGenerationsUsed: 1,
freeUsed: true,
usage: { totalGenerations: 42, totalGenerationCredits: 30 }
}
}
Error codes you should handle:
400 INVALID_PROMPT– prompt validation failed401 AUTH_REQUIRED– missing or invalid JWT402 CREDITS_REQUIRED– user has no remaining credits502 GENERATION_FAILED– upstream service error503 UPSTREAM_BUSY– rate limiting from Ciyuan API
Authentication Flow
JWT Extraction
The getBearerToken function in api/_lib/supabase.js parses the Authorization header:
export function getBearerToken(req) {
const header = req.headers.authorization || '';
const match = header.match(/^Bearer\s+(.+)$/i);
return match ? match[1].trim() : '';
}
Obtaining Tokens
User-driven authentication (frontend applications):
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY);
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google'
});
// Session contains access_token for API calls
Server-to-server authentication (backend services):
Use the service-role key (SUPABASE_SERVICE_ROLE_KEY) with getSupabaseAdminClient from api/_lib/supabase.js to create admin sessions or custom JWTs.
Environment Setup
Copy .env.example to .env and configure:
| Variable | Purpose |
|---|---|
CIYUAN_API_KEY |
Authenticates with Ciyuan image generation service |
VITE_SUPABASE_URL |
Supabase project endpoint |
SUPABASE_SERVICE_ROLE_KEY |
Server-side admin access |
CIYUAN_BASE_URL |
Optional override (default: https://ciyuan.today) |
Step-by-Step Integration
Step 1: Deploy the Backend
The api/ folder structure is designed for Vercel Serverless Functions. Deploying the repository as-is exposes /api/* endpoints automatically.
For local development, run:
npm run dev
Vite proxies /api/* to the built functions during development.
Step 2: Generate an Image from Your Application
// Node.js/Fetch example
async function generateImage(prompt, caseId, supabaseJwt) {
const response = await fetch(
'https://your-deployment.vercel.app/api/generate-image',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${supabaseJwt}`
},
body: JSON.stringify({ prompt, caseId })
}
);
const data = await response.json();
if (!data.ok) {
throw new Error(`${response.status}: ${data.error}`);
}
return {
imageDataUri: data.image, // Ready for <img src="...">
userProfile: data.user // Contains updated credit balance
};
}
Step 3: Handle Credit Management
After each generation, inspect data.user for:
creditBalance– remaining paid generationsfreeGenerationsUsed– consumption of free tierusage.totalGenerations– lifetime stats
Query GET /api/me (defined in api/me.js) to fetch fresh profile data without generating an image.
Step 4: Optional Style Library Integration
The repository includes an agent skill at agents/skills/gpt-image-2-style-library/ that provides structured prompt templates. Install it via the npm package link generated by scripts/generate-style-skill.mjs, then use it to pre-process prompts before API submission.
Code Examples
Browser Client (Vanilla JS)
<!DOCTYPE html>
<html>
<head>
<script type="module">
import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2/+esm';
const supabase = createClient(
'https://YOUR_SUPABASE_URL.supabase.co',
'YOUR_PUBLIC_ANON_KEY'
);
window.signIn = async () => {
await supabase.auth.signInWithOAuth({
provider: 'google',
options: { redirectTo: window.location.href }
});
};
window.generate = async () => {
const { data: { session } } = await supabase.auth.getSession();
if (!session) return alert('Please sign in first');
const prompt = document.getElementById('prompt').value;
const res = await fetch('/api/generate-image', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`
},
body: JSON.stringify({
prompt,
caseId: Date.now() // unique identifier
})
});
const result = await res.json();
if (result.ok) {
document.getElementById('output').src = result.image;
console.log('Credits remaining:', result.user.creditBalance);
} else {
console.error('Generation failed:', result.error);
}
};
</script>
</head>
<body>
<button onclick="signIn()">Sign In with Google</button>
<input id="prompt" placeholder="Describe your image..." size="50">
<button onclick="generate()">Generate</button>
<img id="output" style="max-width: 512px;">
</body>
</html>
Python Server-to-Server
import os
import requests
from supabase import create_client
SUPABASE_URL = os.getenv('SUPABASE_URL')
SERVICE_ROLE_KEY = os.getenv('SUPABASE_SERVICE_ROLE_KEY')
API_BASE = 'https://your-deployment.vercel.app'
supabase = create_client(SUPABASE_URL, SERVICE_ROLE_KEY)
def generate_for_user(user_id: str, prompt: str, case_id: int) -> str:
"""
Returns base64 JPEG data URI for the generated image.
"""
# Create or refresh user session
auth_response = supabase.auth.admin.create_user({
'id': user_id,
'email': f'{user_id}@service.local'
})
# Get JWT for the user
session = supabase.auth.admin.generate_link(
type='magiclink',
email=auth_response.user.email
)
# Call awesome-gpt-image-2 API
response = requests.post(
f'{API_BASE}/api/generate-image',
headers={
'Authorization': f'Bearer {session.properties.access_token}',
'Content-Type': 'application/json'
},
json={'prompt': prompt, 'caseId': case_id}
)
response.raise_for_status()
data = response.json()
if not data.get('ok'):
raise RuntimeError(f"Generation failed: {data.get('error')}")
return data['image'] # data:image/jpeg;base64,...
# Usage
image_uri = generate_for_user(
user_id='org-user-123',
prompt='A cyberpunk street market at night, neon signs, rain',
case_id=10042
)
cURL for Testing
# Check server status (no auth required)
curl https://your-deployment.vercel.app/api/generate-image
# Generate image (requires valid JWT)
curl -X POST https://your-deployment.vercel.app/api/generate-image \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SUPABASE_JWT" \
-d '{"prompt": "A minimalist logo for a tech startup", "caseId": 1}'
# Query current user profile
curl https://your-deployment.vercel.app/api/me \
-H "Authorization: Bearer $SUPABASE_JWT"
Key Source Files Reference
| File Path | Purpose |
|---|---|
api/generate-image.js |
Core handler with prompt validation, credit reservation via reserve_generation_usage RPC, and Ciyuan API forwarding |
api/_lib/supabase.js |
Admin client initialization, getBearerToken extraction, ensureProfileForUser, and isSuperAdminEmail helpers |
api/me.js |
Lightweight endpoint returning authenticated user profile |
src/main.jsx |
Reference implementation showing frontend auth flow and image display |
vercel.json |
Serverless function routing configuration |
Summary
- Deploy the repository to Vercel or any Node-compatible host with the
api/folder as serverless functions - Authenticate users via Supabase OAuth (Google/Watcha) or service-role JWT generation for backend systems
- Call
POST /api/generate-imagewithprompt(max 6000 chars) andcaseIdparameters - Receive a base64 JPEG data URI ready for immediate display or storage
- Monitor credits through the returned
userobject orGET /api/meendpoint - Extend with the style-library skill for structured prompt templates
The modular design of awesome-gpt-image-2 separates concerns cleanly: authentication and credit management live in api/_lib/supabase.js, while generation logic in api/generate-image.js handles upstream communication and response formatting.
Frequently Asked Questions
How do I handle rate limiting from the Ciyuan upstream service?
The api/generate-image.js handler returns 503 UPSTREAM_BUSY when the Ciyuan service is rate-limited. Implement exponential backoff in your client, or queue generation requests internally. The reservation system via reserveGeneration holds credits for 5 minutes, giving you a window to retry without double-charging.
Can I use awesome-gpt-image-2 without Supabase authentication?
Anonymous GET requests to /api/generate-image work for status checks, but POST generation requires a valid JWT. The repository is tightly coupled to Supabase for credit tracking and user profiles. To bypass this, you would need to fork and modify api/_lib/supabase.js to implement an alternative auth provider.
What is the purpose of the caseId parameter?
caseId is an arbitrary numeric identifier passed through to the reservation system for your own bookkeeping. It appears in the reserve_generation_usage RPC call and can be used to associate generations with specific projects, users, or billing categories in your downstream systems. The API does not validate uniqueness—ensure your client manages collision avoidance.
How do I install and use the style-library skill in Claude?
Run the installation command generated by scripts/generate-style-skill.mjs (displayed in the web UI as skillNpm), or manually copy the package from agents/skills/gpt-image-2-style-library/ to your Claude/CodeX environment. The skill exports prompt templates that prepend structured formatting to your raw descriptions before submission to the generation endpoint.
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 →