How GPT-Image2’s Credit-Based Generation System Works

GPT-Image2 protects its image-generation service with a credit-based quota enforced on every request, utilizing Supabase PostgreSQL for atomic transactions and providing both automated billing integration and manual admin overrides.

The credit-based generation system in the freestylefly/awesome-gpt-image-2 repository manages user access to AI image generation through a robust accounting layer built on Supabase. This architecture ensures that every creation request deducts the appropriate credits while maintaining audit trails for billing, memberships, and administrative adjustments.

Core Database Components

The foundation of the credit system rests on two PostgreSQL tables and a set of atomic stored procedures.

User Credit Tables

The schema defined in supabase/migrations/202605090001_user_credits.sql establishes the ledger structure:

  • user_credits – Stores the current balance, purchased credits, and membership credits for each user.
  • credit_transactions – Logs every debit and credit operation for complete auditability.

These tables link to Supabase Auth via user_id, ensuring that credit balances are intrinsically tied to authenticated sessions.

Credit-Adjustment RPCs

Located in api/_lib/billing.js, the system exposes Supabase remote procedure calls (RPCs) that atomically modify balances:

  • grant_user_credits – Adds credits (used for purchases or admin grants).
  • revoke_user_credits – Removes credits (used for refunds or corrections).

Because these execute as database transactions, they prevent race conditions when multiple simultaneous requests attempt to modify the same balance.

The Generation Workflow

Every image creation follows a strict reservation-and-debit pattern to ensure users cannot generate content without sufficient credits.

Credit Reservation Before Generation

When a user submits a generation request to api/generate-image.js, the system performs a硬性 check before contacting external AI providers:

  1. The endpoint queries the current credit_balance from the user_credits table.
  2. It calculates the required creditAmount (typically 1 credit per generation, configurable per model).
  3. It calls grant_user_credits with a negative amount to reserve the credits.
  4. Only upon successful reservation does the request proceed to the external image service (OpenAI, Stability, etc.).

If the reservation fails due to insufficient funds, the API aborts immediately, returning a 402 or similar error without consuming external API resources.

Force Credit Bypass for Privileged Users

The system includes a p_force_credit flag within api/generate-image.js that allows specific accounts to bypass the debit step. This mechanism supports:

  • Internal testing without consuming production credits.
  • Generous free-tier promotions for super-admins.
  • Debugging workflows without financial impact.

When p_force_credit is set to true, the reservation logic is skipped while the generation proceeds normally.

Billing and Payment Integration

The credit system integrates with Stripe and Alipay to convert monetary payments into generation quotas.

Credit Packs and Membership Plans

The checkout flow in api/billing/checkout.js creates orders for credit packs or membership subscriptions. Once payment succeeds, the webhook handler in api/billing/webhook.js executes:

// Executed after Stripe/Alipay confirms payment
await client.rpc('grant_user_credits', {
  user_id: paidOrder.userId,
  amount: paidOrder.credits,   // e.g., 200 credits
  reason: 'credit_pack_purchase',
});

This atomic operation ensures that users receive their purchased credits only after confirmed payment, with the credit_transactions table recording the reason for audit purposes.

Manual Admin Adjustments

Operators can manually adjust balances via the admin endpoint api/admin/credits/adjust.js. This endpoint calls the same grant_user_credits and revoke_user_credits RPCs used by the automated billing system, ensuring that manual interventions remain fully auditable in the transaction log.

Retrieving Credit Status

The front-end queries api/me.js to display real-time quota information. The endpoint returns a JSON payload containing:

  • creditBalance – Current available credits.
  • totalGenerationCredits – Lifetime generation count.
  • purchasedCredits – Credits bought via packs.
  • membershipCredits – Credits included in active subscriptions.

End-to-End Code Examples

Checking Credit Balance (Client-Side)

fetch('https://gpt-image2.canghe.ai/api/me', {
  credentials: 'include'   // Sends Supabase auth cookie
})
  .then(r => r.json())
  .then(data => {
    console.log('Credits remaining:', data.creditBalance);
    console.log('Purchased credits:', data.purchasedCredits);
  });

Requesting Image Generation

fetch('https://gpt-image2.canghe.ai/api/generate-image', {
  method: 'POST',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    prompt: 'A futuristic cityscape at sunset, photorealistic',
    // Optional: bypass credit check for admin/testing
    p_force_credit: false
  })
})
  .then(r => r.json())
  .then(res => {
    console.log('Generated image:', res.imageUrl);
    console.log('New balance:', res.creditBalance);
  });

Server-Side Credit Top-Up (Webhook Handler)

// Located in api/billing/webhook.js
async function handleSuccessfulPayment(paidOrder) {
  const { error } = await client.rpc('grant_user_credits', {
    user_id: paidOrder.userId,
    amount: paidOrder.credits,
    reason: paidOrder.planType  // 'credit_pack' or 'membership'
  });
  
  if (error) throw new Error(`Credit grant failed: ${error.message}`);
  return { success: true, granted: paidOrder.credits };
}

Summary

  • Atomic transactions via Supabase RPCs prevent race conditions and double-spending of credits.
  • Reservation pattern in api/generate-image.js ensures external AI costs are never incurred for users with insufficient balances.
  • Flexible billing supports both one-time credit packs and recurring membership plans through Stripe/Alipay integration.
  • Audit trail in credit_transactions provides complete visibility into every credit movement, including manual admin adjustments.
  • Privileged bypass via p_force_credit enables testing and promotional use cases without disrupting the accounting system.

Frequently Asked Questions

How does GPT-Image2 prevent users from overdrawing credits?

The system uses atomic RPC transactions inside api/_lib/billing.js. When grant_user_credits is called with a negative amount for reservation, the database checks the current balance within the same transaction. If two simultaneous requests attempt to debit the last remaining credit, PostgreSQL’s row locking ensures only one succeeds, while the other receives an insufficient-funds error.

What happens if an image generation fails after credits are reserved?

The reservation logic in api/generate-image.js treats the RPC call as a temporary hold. If the subsequent call to the external AI service (OpenAI or Stability) fails or times out, the application logic rolls back the transaction or issues a compensating grant_user_credits call to return the reserved amount to the user's balance.

Can administrators bypass the credit system for testing?

Yes. The p_force_credit parameter in api/generate-image.js allows privileged accounts to skip the debit step entirely. When this flag is set to true, the generation proceeds without checking user_credits or writing to credit_transactions, making it ideal for internal QA and super-admin demonstrations.

What database powers the credit system?

The system runs on Supabase, which provides PostgreSQL as the underlying datastore along with built-in authentication. The migration files supabase/migrations/202605090001_user_credits.sql and supabase/migrations/20260509090000_membership_billing.sql define the tables, indexes, and stored procedures that enforce data integrity for all credit operations.

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 →