# How GPT-Image2 API Calls Are Proxied with Credit Enforcement in awesome-gpt-image-2

> Learn how awesome-gpt-image-2 proxies GPT-Image2 API calls and enforces user credits using Supabase stored procedures for secure transactions.

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

---

**The awesome-gpt-image-2 service proxies image generation requests to the Ciyuan API while enforcing user credits through Supabase stored procedures that reserve, complete, or rollback credit transactions before allowing the upstream call to proceed.**

The awesome-gpt-image-2 repository implements a robust credit-based access layer for GPT-Image2 generation capabilities. By intercepting requests at the `/api/generate-image` endpoint, the system ensures users have sufficient credits before proxying calls to the external image service, preventing unauthorized usage and maintaining accurate billing records.

## The Proxy Architecture Overview

The system operates as a transparent middleware layer between client applications and the external Ciyuan image generation service. When a client submits a generation request, the backend first validates authentication and reserves the required credits through Supabase. Only after a successful credit reservation does the proxy forward the request to `https://ciyuan.today/v1/images/generations`. This architecture ensures that credit enforcement happens atomically before any external API costs are incurred.

## Step-by-Step Credit Enforcement Flow

### 1. Request Validation and Authentication

The handler in [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js) (lines 59‑78) strictly validates incoming traffic. It accepts only **GET** requests for profile queries and **POST** requests for actual image generation. The code verifies that the server environment contains the required `CIYUAN_API_KEY` and valid Supabase credentials, then confirms the user is authenticated through the Supabase auth context before proceeding.

### 2. Credit Reservation via Supabase

For generation requests, the system calls the Supabase stored procedure **`reserve_generation_usage`** through the helper functions `reserveGeneration` and `reserveCreditGeneration` (lines 59‑88). The reservation accepts parameters including the user ID, case ID, prompt, and a critical flag **`p_force_credit`**:

- **Normal users**: `p_force_credit: false` (consumes free quota first)
- **Super-admin users**: `p_force_credit: true` (bypasses free tier and forces credit usage)

### 3. Insufficient Credit Handling (HTTP 402)

If the stored procedure returns an error containing the text `CREDITS_REQUIRED`, the handler immediately catches this exception (lines 104‑112) and returns **HTTP 402** to the client. This prevents the proxy from ever contacting the upstream Ciyuan service when the user lacks sufficient funds, ensuring no external API costs are generated for invalid requests.

### 4. Proxying to the Ciyuan API

Upon successful credit reservation, the `generateImage` function (lines 26‑44) forwards the request to the Ciyuan service. The proxy injects the server-side `CIYUAN_API_KEY` into the request headers and transmits the user's prompt, model selection, image size, and other generation parameters to `https://ciyuan.today/v1/images/generations`.

### 5. Success Path: Completing the Reservation

When the upstream API returns valid image data, the handler invokes **`complete_generation_reservation`** via the `completeReservation` helper (lines 5‑27). This permanently deducts the reserved credits from the user's balance. The response includes both the base64-encoded image data and an updated user profile reflecting the new credit balance through the `profileFromReservation` helper.

### 6. Failure Path: Releasing Reserved Credits

If the Ciyuan API fails—whether due to rate limiting, service unavailability, or generation errors—the system calls **`release_generation_reservation`** through `releaseReservation` (lines 12‑24). This returns the reserved credits to the user's available balance. The handler returns appropriate error codes such as `UPSTREAM_BUSY` or `GENERATION_FAILED` (lines 28‑44) while refreshing the user profile to display the current credit state.

## Key Implementation Files

- **[`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js)**: The main entry point containing request validation, credit orchestration, and the Ciyuan proxy logic.
- **[`api/_lib/supabase.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js)**: Provides the Supabase client initialization and authentication helpers including `getAuthContext` and `getProfileById`.
- **[`api/me.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/me.js)**: Exposes the current user's profile including credit balances for frontend display.
- **[`supabase/migrations/202605090001_user_credits.sql`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/supabase/migrations/202605090001_user_credits.sql)**: Defines the database schema for credit balances and transaction history.

## Client Integration Example

Frontend applications interact with the proxy through standard HTTP requests. The backend handles all credit enforcement transparently:

```javascript
async function generateImage(prompt, caseId) {
  const res = await fetch('/api/generate-image', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ prompt, caseId })
  });
  const data = await res.json();
  if (!data.ok) throw new Error(data.error);
  return data.image; // base64 JPEG
}

```

After a successful generation, update the UI with the returned credit balance:

```javascript
const { image, user } = await generateImage(prompt, caseId);
setImageSrc(image);
setUserCredits(user.creditBalance);

```

## Summary

- The **`/api/generate-image`** endpoint acts as a credit-enforcing proxy to the Ciyuan GPT-Image2 service.
- **Supabase stored procedures** (`reserve_generation_usage`, `complete_generation_reservation`, `release_generation_reservation`) manage atomic credit transactions.
- Users receive **HTTP 402** (`CREDITS_REQUIRED`) when attempting generation without sufficient funds.
- The system only contacts the external API after successfully reserving credits, ensuring no wasted external API calls.
- Failed upstream requests automatically trigger credit rollback via the release reservation procedure.

## Frequently Asked Questions

### What happens when a user has insufficient credits for image generation?

The Supabase stored procedure `reserve_generation_usage` returns a `CREDITS_REQUIRED` error, which the handler in [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js) catches and translates into an HTTP 402 response. The client receives this error before any request reaches the external Ciyuan API, ensuring the user's credit balance remains unchanged and no external costs are incurred.

### How does the system handle failures from the upstream Ciyuan API?

If the Ciyuan service returns an error or times out, the handler invokes `release_generation_reservation` through the `releaseReservation` helper. This returns the previously reserved credits to the user's account and returns an error code such as `UPSTREAM_BUSY` or `GENERATION_FAILED` to the client, maintaining credit accuracy even during service disruptions.

### What is the purpose of the `p_force_credit` parameter in the reservation system?

The `p_force_credit` boolean flag passed to `reserve_generation_usage` controls quota consumption behavior. When set to `false` (default for normal users), the system consumes free tier allowances before deducting paid credits. When set to `true` (used for super-admin users), the system bypasses free quotas and immediately deducts from the credit balance, useful for testing paid flows or administrative operations.

### Where is the credit balance stored and how is it accessed?

User credit balances are stored in the Supabase database schema defined in [`supabase/migrations/202605090001_user_credits.sql`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/supabase/migrations/202605090001_user_credits.sql). The [`api/me.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/me.js) endpoint exposes the current balance to the frontend, while [`api/_lib/supabase.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js) provides the `getProfileById` helper that the generation endpoint uses to refresh and return updated balances after each transaction.