# Daily Generation Limits and AI Credits System in prompts.chat: Complete Technical Guide

> Understand prompts.chat's AI credits system and daily generation limits. Learn how credits are tracked and replenished for seamless AI media generation. Get the technical guide now.

- Repository: [Fatih Kadir Akın/prompts.chat](https://github.com/f/prompts.chat)
- Tags: how-to-guide
- Published: 2026-04-02

---

**The prompts.chat AI credits system limits users to a default of 3 generated media items per day by tracking `generationCreditsRemaining` on the User table, automatically decrementing credits atomically on each successful generation, and restoring quotas via a protected cron job at midnight.**

The open-source prompts.chat repository implements a robust rate-limiting mechanism to prevent abuse of AI media generation APIs. This system balances user experience with resource protection through database-level atomic operations, scheduled credit resets, and administrative override capabilities.

## Database Schema for Credit Management

The foundation of the AI credits system rests on three columns defined in the **User** model within `prisma/schema.prisma`. These fields store the complete state necessary for quota enforcement:

- **`dailyGenerationLimit`** – The maximum number of credits granted per day (defaults to 3).
- **`generationCreditsRemaining`** – The current balance of available generations for today.
- **`generationCreditsResetAt`** – Timestamp tracking when credits were last replenished.

```prisma
// prisma/schema.prisma (lines 31-34)
model User {
  dailyGenerationLimit       Int      @default(3)
  generationCreditsRemaining Int      @default(3)
  generationCreditsResetAt   DateTime @default(now())
  // ... other fields
}

```

This schema design allows for per-user customization while maintaining sensible defaults for new registrations.

## Checking Credit Status and Consuming Credits

The [`src/app/api/media-generate/route.ts`](https://github.com/f/prompts.chat/blob/main/src/app/api/media-generate/route.ts) file handles both credit inquiry and consumption through distinct HTTP methods.

### Fetching Current Quota (GET)

When clients query available credits, the endpoint returns the remaining count, daily limit, and a boolean flag indicating whether generation is permitted:

```typescript
// src/app/api/media-generate/route.ts (lines 22-42)
export async function GET(request: Request) {
  const user = await getCurrentUser();
  return Response.json({
    credits: user.generationCreditsRemaining,
    dailyLimit: user.dailyGenerationLimit,
    canGenerate: user.generationCreditsRemaining > 0 && !user.isBanned
  });
}

```

### Atomic Credit Consumption (POST)

Upon receiving a generation request, the server validates available credits before invoking the media-generation plugin. Crucially, the system uses Prisma's atomic **decrement** operation to prevent race conditions when multiple requests arrive simultaneously:

```typescript
// src/app/api/media-generate/route.ts (lines 53-80)
export async function POST(request: Request) {
  const user = await getCurrentUser();
  
  if (user.generationCreditsRemaining <= 0) {
    return Response.json({ error: 'No credits remaining' }, { status: 403 });
  }
  
  await prisma.user.update({
    where: { id: user.id },
    data: { 
      generationCreditsRemaining: { decrement: 1 } 
    }
  });
  
  // Proceed with media generation...
}

```

This atomic decrement ensures accurate credit tracking even under high concurrency.

## Automated Daily Credit Resets

The system restores user quotas automatically through a protected cron endpoint at [`src/app/api/cron/reset-credits/route.ts`](https://github.com/f/prompts.chat/blob/main/src/app/api/cron/reset-credits/route.ts).

### Cron Job Implementation

A Vercel or GitHub Actions scheduled task invokes `POST /api/cron/reset-credits` with a secret authorization header. The endpoint executes a raw SQL update to efficiently reset all users simultaneously:

```typescript
// src/app/api/cron/reset-credits/route.ts (lines 38-45)
export async function POST(request: Request) {
  const authHeader = request.headers.get('authorization');
  if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 });
  }
  
  await prisma.$executeRaw`
    UPDATE "User" 
    SET "generationCreditsRemaining" = "dailyGenerationLimit",
        "generationCreditsResetAt" = NOW()
  `;
  
  return Response.json({ success: true, resetCount: ... });
}

```

This approach scales efficiently because it performs a single database operation across all records rather than iterating through individual users.

## Administrative Credit Controls

Administrators can override individual user limits through a dedicated API endpoint and React-based admin interface.

### API Endpoint for Limit Adjustments

The `src/app/api/admin/users/[id]/route.ts` file exposes a **PATCH** handler that accepts new daily limits and optionally resets remaining credits immediately:

```typescript
// src/app/api/admin/users/[id]/route.ts (lines 16-60)
export async function PATCH(
  request: Request,
  { params }: { params: { id: string } }
) {
  const { dailyGenerationLimit, resetCredits } = await request.json();
  
  const updateData: any = { dailyGenerationLimit };
  
  if (resetCredits) {
    updateData.generationCreditsRemaining = dailyGenerationLimit;
  }
  
  const updatedUser = await prisma.user.update({
    where: { id: params.id },
    data: updateData
  });
  
  return Response.json(updatedUser);
}

```

### Admin User Interface

The [`src/components/admin/users-table.tsx`](https://github.com/f/prompts.chat/blob/main/src/components/admin/users-table.tsx) component (lines 55-64) provides an "Edit Credits" dialog that interfaces with this PATCH endpoint, allowing non-technical administrators to adjust quotas through the web UI rather than manual database queries.

## Client-Side Integration Example

Applications consuming the prompts.chat API typically implement this flow:

```typescript
// 1. Check current quota
const { credits, dailyLimit, canGenerate } = await fetch('/api/media-generate')
  .then(r => r.json());

// 2. Conditionally enable generation button
if (canGenerate) {
  const response = await fetch('/api/media-generate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      prompt: 'A cyberpunk city at dusk',
      model: 'stable-diffusion',
      type: 'image',
      provider: 'stability'
    })
  });
  // Server automatically decrements credits on success
}

```

## Manual Operations

### Triggering Credit Reset Manually

For testing or emergency resets, administrators can invoke the cron endpoint directly:

```bash
curl -X POST https://your-domain.com/api/cron/reset-credits \
  -H "Authorization: Bearer YOUR_CRON_SECRET"

```

### Updating User Limits via API

To grant specific users higher quotas without UI interaction:

```bash
curl -X PATCH https://your-domain.com/api/admin/users/USER_ID \
  -H "Content-Type: application/json" \
  -d '{"dailyGenerationLimit": 10, "resetCredits": true}'

```

## Summary

- **Three database fields** (`dailyGenerationLimit`, `generationCreditsRemaining`, `generationCreditsResetAt`) in `prisma/schema.prisma` store the complete credit state for each user.
- **Atomic decrement operations** in [`src/app/api/media-generate/route.ts`](https://github.com/f/prompts.chat/blob/main/src/app/api/media-generate/route.ts) prevent race conditions when consuming credits during high-traffic generation requests.
- **Default allowance** of 3 credits per day applies automatically to new users unless overridden by administrators.
- **Protected cron endpoint** at [`src/app/api/cron/reset-credits/route.ts`](https://github.com/f/prompts.chat/blob/main/src/app/api/cron/reset-credits/route.ts) restores all user quotas daily using raw SQL for performance.
- **Admin controls** allow dynamic adjustment of individual limits through both REST API (`/api/admin/users/[id]`) and React UI components without requiring database access.

## Frequently Asked Questions

### How does prompts.chat prevent users from exceeding their daily generation limits?

The system enforces limits through server-side validation in [`src/app/api/media-generate/route.ts`](https://github.com/f/prompts.chat/blob/main/src/app/api/media-generate/route.ts). Before processing any generation request, the handler checks `generationCreditsRemaining` and rejects requests with a 403 status if the value is zero or negative. Credits are then decremented atomically using Prisma's decrement operator to ensure accuracy even with concurrent requests.

### What happens when the daily generation limit is increased for an existing user?

When administrators call the PATCH endpoint at `src/app/api/admin/users/[id]/route.ts` with a higher `dailyGenerationLimit`, the change applies immediately to future cycles. If the `resetCredits` flag is included in the request, the system also updates `generationCreditsRemaining` to match the new limit instantly, granting additional generations for the current day.

### How can I manually reset credits for all users before the scheduled cron job?

Send a POST request to `/api/cron/reset-credits` with the `Authorization: Bearer YOUR_CRON_SECRET` header. This triggers the same logic as the automated midnight reset, executing a raw SQL update that copies `dailyGenerationLimit` into `generationCreditsRemaining` for every user in the database and updates the `generationCreditsResetAt` timestamp.

### Why does the system use Prisma's atomic decrement instead of standard update operations?

Atomic decrement prevents **race conditions** where two simultaneous generation requests might both read the same credit balance before either writes back, resulting in only one credit being deducted for two generations. By using Prisma's `{ decrement: 1 }` operation, the database handles the subtraction at the SQL level, ensuring accurate counting even under heavy concurrent load.