ShipAny Docs

Credits

The credits module (src/modules/credits/service.ts) provides grant, consume, revoke, getBalance, and getHistory.

How Credits Are Granted

SceneTriggerConfiguration
SignupAuto-grant after registrationAdmin Settings: initial_credits_enabled, initial_credits_amount, initial_credits_valid_days (0 = never expires), initial_credits_description
PaymentOrder becomes PAIDcredits + creditsValidDays on the product in src/config/pricing.ts; subscriptions expire at period end
ManualAdmin panel → CreditsGrant with scene GIFT / REWARD

Consumption (FIFO)

  • Earliest-expiring credits are consumed first (expiresAt ascending, never-expiring last)
  • Consumption runs in a database transaction, batched (up to 1000 credits per batch)
  • Only valid credits count toward the balance: active, not expired, not deleted
import { consume } from '@/modules/credits/service';

const result = await consume({
  userId,
  credits: 10,
  scene: 'ai_generation',
  description: 'Generate image',
});
// result.success === false when the balance is insufficient

Expiration

  • Each grant carries an optional expiresAt (null = never expires)
  • One-time purchases: now + creditsValidDays
  • Subscriptions: expires at currentPeriodEnd — renewal grants a fresh batch

Records

Every grant/consume is a row in the credit table with transactionType (GRANT/CONSUME), transactionScene, remainingCredits, expiresAt, and a consumedDetail JSON trail — so balances and history are fully auditable.