LogoNEXTDEVKIT Docs

API Reference

Complete API reference for the credits system functions and server actions

📚 Overview

This page documents all available functions and server actions in the credits system. All functions are fully type-safe with TypeScript and integrated with Drizzle ORM.

🔧 Configuration Functions

Import from @/config/credits

isCreditsEnabled()

Check if the credits system is enabled.

Usage:

import { isCreditsEnabled } from "@/config/credits";

if (isCreditsEnabled()) {
  // Credits system is active
}

Returns: boolean


getCreditPackages()

Get all available credit packages.

Usage:

import { getCreditPackages } from "@/config/credits";

const packages = getCreditPackages();
// [{ id: 'lite', credits: 100, ... }, ...]

Returns: CreditPackage[]


getCreditPackageById(id: string)

Get a specific credit package by ID.

Parameters:

  • id - Package ID (e.g., "lite", "standard", "pro", "max")

Usage:

import { getCreditPackageById } from "@/config/credits";

const package = getCreditPackageById("pro");
if (package) {
  console.log(`${package.name}: ${package.credits} credits for $${package.amount}`);
}

Returns: CreditPackage | null


getCreditConsumption(service: string)

Get credit consumption rate for a service.

Parameters:

  • service - Service identifier (e.g., "google:chat", "google:image")

Usage:

import { getCreditConsumption } from "@/config/credits";

const cost = getCreditConsumption("google:chat");
console.log(`Chat costs ${cost} credits per request`);

Returns: number - Credits consumed per use (defaults to 1 if not configured)


getSubscriptionPlanCredits(planId: string)

Get credits configuration for a subscription plan.

Parameters:

  • planId - Plan identifier (e.g., "free", "pro")

Usage:

import { getSubscriptionPlanCredits } from "@/config/credits";

const planCredits = getSubscriptionPlanCredits("pro");
if (planCredits?.enabled) {
  console.log(`Pro users get ${planCredits.monthlyGrant} credits/month`);
}

Returns: PlanCreditsConfig | null


isRegistrationCreditsEnabled()

Check if registration bonus credits are enabled.

Usage:

import { isRegistrationCreditsEnabled } from "@/config/credits";

if (isRegistrationCreditsEnabled()) {
  await grantRegistrationBonus(userId);
}

Returns: boolean


allowFreeUserPurchasePackages()

Check if free users can purchase credit packages.

Usage:

import { allowFreeUserPurchasePackages } from "@/config/credits";

if (!isPaidUser && !allowFreeUserPurchasePackages()) {
  return "Upgrade to purchase credits";
}

Returns: boolean


💰 Credit Grant Functions

Import from @/credits/actions

grantCredits(params: GrantCreditsParams)

Core function to grant credits to a user.

Parameters:

interface GrantCreditsParams {
  userId: string;              // User ID
  amount: number;              // Credits to grant
  type: CreditTransactionType; // Transaction type
  validityDays?: number;       // Days until expiration
  sourcePlan?: string;         // Source plan ID
  grantPeriod?: string;        // YYYY-MM for monthly grants
  description?: string;        // Transaction description
  packageId?: string;          // Credit package ID
  purchaseId?: string;         // Purchase record ID
}

Usage:

import { grantCredits, CreditTransactionType } from "@/credits/actions";

const result = await grantCredits({
  userId: "user_123",
  amount: 100,
  type: CreditTransactionType.PURCHASE,
  validityDays: 90,
  packageId: "lite",
  description: "Purchased Lite package",
});

console.log(`Transaction ID: ${result.transactionId}`);
console.log(`Expires: ${result.expirationDate}`);

Returns:

{
  transactionId: string;
  batchId?: string;
  expirationDate?: Date;
}

grantRegistrationBonus(userId: string)

Grant registration bonus credits to a new user.

Parameters:

  • userId - User ID

Usage:

import { grantRegistrationBonus } from "@/credits/actions";

// Called after user registration
const result = await grantRegistrationBonus("user_123");

Returns: Promise<{ transactionId: string; batchId?: string; expirationDate?: Date; }>


grantSubscriptionCredits()

Grant monthly credits to a subscription user.

Parameters:

userId: string;
amount: number;
planId: string;
validityDays: number;
grantPeriod?: string;  // YYYY-MM format
purchaseId?: string;

Usage:

import { grantSubscriptionCredits } from "@/credits/actions";

await grantSubscriptionCredits(
  "user_123",
  200,           // Amount
  "pro",         // Plan ID
  30,            // Validity days
  "2024-01",     // Grant period
  "purchase_id"
);

Returns: Promise<{ transactionId: string; batchId?: string; expirationDate?: Date; }>


grantPurchasedCredits(params)

Grant credits after a credit package purchase.

Parameters:

{
  userId: string;
  priceId: string;   // Stripe/Creem price ID
  purchaseId: string; // Purchase record ID
}

Usage:

import { grantPurchasedCredits } from "@/credits/actions";

// Called by payment webhook
await grantPurchasedCredits({
  userId: "user_123",
  priceId: "price_xxx",
  purchaseId: "purchase_xxx",
});

Returns: Promise<void>


🔥 Credit Consumption Functions

consumeCreditsForService(params)

Consume credits for a service usage.

Parameters:

{
  userId: string;
  service: string;           // Service identifier
  amount?: number;           // Optional: override configured amount
  description?: string;
  metadata?: Record<string, any>;
}

Usage:

import { consumeCreditsForService } from "@/credits/actions";

// Use configured consumption rate
const result = await consumeCreditsForService({
  userId: "user_123",
  service: "google:chat",
});

// Or specify custom amount
const result = await consumeCreditsForService({
  userId: "user_123",
  service: "custom_ai",
  amount: 10,
  description: "Custom AI model inference",
  metadata: { model: "gpt-4", tokens: 1500 },
});

console.log(`Consumed: ${result.consumedAmount} credits`);
console.log(`New balance: ${result.newBalance} credits`);

Returns:

{
  transactionId: string;
  consumedAmount: number;
  newBalance: number;
  consumptionLog: Array<{
    batchId: string;
    consumed: number;
    batchRemaining: number;
  }>;
}

Errors:

  • Throws Error if insufficient credits
  • Throws Error if invalid service/amount

consumeCreditsWithFIFO(params: ConsumeCreditsParams)

Low-level FIFO credit consumption (used by consumeCreditsForService).

Parameters:

interface ConsumeCreditsParams {
  userId: string;
  amount: number;
  service: string;
  description?: string;
  metadata?: Record<string, any>;
}

Returns:

{
  transactionId: string;
  consumptionLog: Array<{
    batchId: string;
    consumed: number;
    batchRemaining: number;
  }>;
  newBalance: number;
}

📊 Query Functions

getUserCreditsInfo(params)

Get comprehensive credits information for a user.

Parameters:

{
  userId: string;
}

Usage:

import { getUserCreditsInfo } from "@/credits/actions";

const { data } = await getUserCreditsInfo({ userId: "user_123" });

if (data) {
  console.log(`Available: ${data.availableCredits}`);
  
  if (data.nextExpiringBatch) {
    console.log(`Expiring: ${data.nextExpiringBatch.amount} on ${data.nextExpiringBatch.expiresAt}`);
  }
  
  if (data.nextGrantInfo) {
    console.log(`Next grant: ${data.nextGrantInfo.amount} on ${data.nextGrantInfo.grantDate}`);
  }
}

Returns:

{
  data?: {
    availableCredits: number;
    nextExpiringBatch: {
      amount: number;
      expiresAt: Date;
    } | null;
    nextGrantInfo: {
      amount: number;
      grantDate: Date;
      planName: string;
    } | null;
  };
  serverError?: string;
}

getUserTransactions(params)

Get user's credit transaction history with pagination.

Parameters:

{
  userId: string;
  pageIndex?: number;  // Default: 0
  pageSize?: number;   // Default: 10, max: 100
}

Usage:

import { getUserTransactions } from "@/credits/actions";

const { data } = await getUserTransactions({
  userId: "user_123",
  pageIndex: 0,
  pageSize: 20,
});

if (data) {
  console.log(`Total transactions: ${data.total}`);
  console.log(`Pages: ${data.pageCount}`);
  
  data.items.forEach(transaction => {
    console.log(`${transaction.type}: ${transaction.amount} credits`);
  });
}

Returns:

{
  data?: {
    items: Array<{
      id: string;
      type: string;
      amount: number;
      description: string | null;
      status: string;
      sourcePlan: string | null;
      createdAt: Date;
    }>;
    total: number;
    pageIndex: number;
    pageSize: number;
    pageCount: number;
  };
  serverError?: string;
}

🤖 Automated Jobs

processDailyGrant()

Process daily subscription credit grants (called by cron).

Usage:

import { processDailyGrant } from "@/credits/actions";

// Called by /api/jobs/credits/grant
const results = await processDailyGrant();

console.log(`Processed: ${results.processed}`);
console.log(`Successful: ${results.successful}`);
console.log(`Skipped: ${results.skipped}`);
console.log(`Failed: ${results.failed}`);

Returns:

{
  processed: number;   // Total subscriptions processed
  successful: number;  // Successfully granted
  skipped: number;     // Already granted this period
  failed: number;      // Failed to grant
  results: Array<{
    userId: string;
    success: boolean;
    error?: string;
    transactionId?: string;
    amount?: number;
    grantPeriod?: string;
  }>;
}

processExpiredCredits()

Process expired credit batches (called by cron).

Usage:

import { processExpiredCredits } from "@/credits/actions";

// Called by /api/jobs/credits/expire
const result = await processExpiredCredits();

console.log(`Batches expired: ${result.processedBatches}`);
console.log(`Users affected: ${result.processedUsers}`);
console.log(`Total expired: ${result.totalExpiredAmount}`);

Returns:

{
  processedBatches: number;
  processedUsers: number;
  totalExpiredAmount: number;
}

🎯 Types

CreditTransactionType

enum CreditTransactionType {
  PURCHASE = "purchase",
  CONSUMPTION = "consumption",
  MONTHLY_GRANT = "monthly_grant",
  REGISTRATION_BONUS = "registration_bonus",
  EXPIRATION = "expiration",
}

CreditPackage

interface CreditPackage {
  id: string;
  name?: string;
  description?: string;
  credits: number;
  priceId: string;
  amount: number;
  currency: string;
  popular?: boolean;
  validityDays?: number;
  bonus: number;
}

PlanCreditsConfig

interface PlanCreditsConfig {
  id: string;
  enabled: boolean;
  monthlyGrant: number;
  validityDays: number;
}

🛡️ Error Handling

All functions properly handle errors and throw typed exceptions:

try {
  await consumeCreditsForService({
    userId: "user_123",
    service: "google:chat",
  });
} catch (error) {
  if (error instanceof Error) {
    if (error.message.includes("Insufficient credits")) {
      // Handle insufficient credits
      showUpgradeModal();
    } else if (error.message.includes("User balance not found")) {
      // Handle missing balance
      await initializeUserBalance();
    } else {
      // Handle other errors
      console.error("Credit operation failed:", error.message);
    }
  }
}