How GPT-Image2 API Calls Are Proxied with Credit Enforcement in awesome-gpt-image-2
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 (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: The main entry point containing request validation, credit orchestration, and the Ciyuan proxy logic.api/_lib/supabase.js: Provides the Supabase client initialization and authentication helpers includinggetAuthContextandgetProfileById.api/me.js: Exposes the current user's profile including credit balances for frontend display.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:
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:
const { image, user } = await generateImage(prompt, caseId);
setImageSrc(image);
setUserCredits(user.creditBalance);
Summary
- The
/api/generate-imageendpoint 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 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. The api/me.js endpoint exposes the current balance to the frontend, while api/_lib/supabase.js provides the getProfileById helper that the generation endpoint uses to refresh and return updated balances after each transaction.
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 →