# How to Integrate awesome-gpt-image-2 with Other Applications: A Complete API Guide

> Integrate awesome-gpt-image-2 with your apps using its REST API. Learn how to call the generate-image endpoint with Supabase JWT and get base64 JPEG data. Unlock image generation.

- Repository: [苍何/awesome-gpt-image-2](https://github.com/freestylefly/awesome-gpt-image-2)
- Tags: api-reference
- Published: 2026-08-27

---

**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.

```javascript
// Response structure
{
  ok: true,
  authRequired: boolean,
  freeUsed: boolean,
  user: <profile|null>
}

```

The implementation in [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/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 |

```javascript
// 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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js) parses the Authorization header:

```javascript
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):

```javascript
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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/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:

```bash
npm run dev

```

Vite proxies `/api/*` to the built functions during development.

### Step 2: Generate an Image from Your Application

```javascript
// 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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/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)

```html
<!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

```python
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

```bash

# 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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js) | Core handler with prompt validation, credit reservation via `reserve_generation_usage` RPC, and Ciyuan API forwarding |
| [`api/_lib/supabase.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js) | Admin client initialization, `getBearerToken` extraction, `ensureProfileForUser`, and `isSuperAdminEmail` helpers |
| [`api/me.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/me.js) | Lightweight endpoint returning authenticated user profile |
| [`src/main.jsx`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/main.jsx) | Reference implementation showing frontend auth flow and image display |
| [`vercel.json`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js), while generation logic in [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/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`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/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.