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 failed
  • 401 AUTH_REQUIRED – missing or invalid JWT
  • 402 CREDITS_REQUIRED – user has no remaining credits
  • 502 GENERATION_FAILED – upstream service error
  • 503 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 generations
  • freeGenerationsUsed – consumption of free tier
  • usage.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-image with prompt (max 6000 chars) and caseId parameters
  • Receive a base64 JPEG data URI ready for immediate display or storage
  • Monitor credits through the returned user object or GET /api/me endpoint
  • 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →