Files
igny8/docs/40-WORKFLOWS/CREDIT-SYSTEM.md
IGNY8 VPS (Salman) 4bffede052 docs & ux improvmeents
2025-12-25 20:31:58 +00:00

9.2 KiB

Usage & Content System

Last Verified: December 25, 2025


Overview

IGNY8 uses a content-based allowance system. Users see "Content Pieces" while the backend tracks detailed credit consumption for internal cost monitoring.

User View: 47/50 Content Pieces Remaining
Backend Tracks: Idea credits, content credits, image credits (for cost analysis)


How It Works

User-Facing (Simple)

What Users See Description
Content Pieces Monthly allowance of pages/articles
X/Y Remaining Used vs total for the month
Upgrade Plan Get more content pieces

Backend (Detailed - Internal Only)

Credit Type Used For Tracked For
Idea Credits Clustering, idea generation Cost analysis
Content Credits Article generation Usage limits
Image Credits Image generation Cost analysis
Optimization Credits SEO optimization (future) Cost analysis

Plan Allowances

Plan Content Pieces/Month Sites Users
Starter 50 2 2
Growth 200 5 3
Scale 500 Unlimited 5

Included with every content piece:

  • AI keyword clustering
  • AI idea generation
  • AI content writing (1000-2000 words)
  • 3 images (1 featured + 2 in-article)
  • Internal linking
  • SEO optimization
  • WordPress publishing

Backend Soft Limits (Hidden from Users)

To prevent abuse, the backend enforces hidden limits:

Limit Starter Growth Scale
Keyword imports/mo 500 2,000 5,000
Clustering operations 100 400 1,000
Idea generations 150 600 1,500
Images generated 200 800 2,000

If users hit these limits, they see: "You've reached your preparation limit for this month."


Content Deduction Flow

┌─────────────────────────────────────────────────────────────────┐
│                   CONTENT CREATION FLOW                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  User clicks                Check                 Generate       │
│  "Generate"   ──────►      Allowance  ──────►    Content        │
│                               │                      │          │
│                               │ Limit                │          │
│                               │ Reached              ▼          │
│                               ▼                  Deduct 1       │
│                          Show Upgrade            Content        │
│                          Modal                   Piece          │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Operations & Credit Costs

Planner Operations

Operation Credits Type
Add keyword 0 Free
Auto-cluster keywords 1 Idea
Generate content ideas 1 per idea Idea

Writer Operations

Operation Credits Type
Create task 0 Free
Generate content 1 Content
Regenerate content 1 Content
Generate images 1 per image Image
Regenerate image 1 Image
Edit content 0 Free

Automation Operations

Operation Credits Type
Run automation Sum of operations Mixed
Pause/resume 0 Free

Publisher Operations

Operation Credits Type
Publish to WordPress 0 Free
Sync from WordPress 0 Free

Optimizer Operations (Future)

Operation Credits Type
Optimize content 1 Optimization
Batch optimize 1 per item Optimization

Database Models

CreditBalance

class CreditBalance(models.Model):
    account = models.ForeignKey(Account)
    site = models.ForeignKey(Site, null=True)
    
    idea_credits = models.IntegerField(default=0)
    content_credits = models.IntegerField(default=0)
    image_credits = models.IntegerField(default=0)
    optimization_credits = models.IntegerField(default=0)
    
    period_start = models.DateField()
    period_end = models.DateField()

CreditUsage

class CreditUsage(models.Model):
    account = models.ForeignKey(Account)
    site = models.ForeignKey(Site, null=True)
    user = models.ForeignKey(User)
    
    credit_type = models.CharField()  # idea/content/image/optimization
    amount = models.IntegerField()
    operation = models.CharField()    # generate_content, etc.
    
    created_at = models.DateTimeField(auto_now_add=True)

Business Logic

CreditService

Location: backend/igny8_core/business/billing/services.py

Key Methods:

class CreditService:
    def check_balance(account, site, credit_type, amount) -> bool:
        """Check if sufficient credits available"""
        
    def deduct_credits(account, site, user, credit_type, amount, operation) -> bool:
        """Deduct credits and log usage"""
        
    def get_balance(account, site) -> CreditBalance:
        """Get current balance"""
        
    def reset_monthly_credits(account) -> None:
        """Reset credits at period start"""
        
    def add_credits(account, credit_type, amount, reason) -> None:
        """Add credits (admin/purchase)"""

Usage in AI Operations

# In content generation service
def generate_content(task, user):
    # 1. Check balance
    if not credit_service.check_balance(
        account=task.site.account,
        site=task.site,
        credit_type='content',
        amount=1
    ):
        raise InsufficientCreditsError()
    
    # 2. Execute AI function
    content = ai_engine.generate_content(task)
    
    # 3. Deduct credits
    credit_service.deduct_credits(
        account=task.site.account,
        site=task.site,
        user=user,
        credit_type='content',
        amount=1,
        operation='generate_content'
    )
    
    return content

API Responses

Successful Deduction

{
  "success": true,
  "data": { ... },
  "credits_used": {
    "type": "content",
    "amount": 1
  },
  "balance": {
    "content_credits": 49
  }
}

Insufficient Credits

HTTP 402 Payment Required

{
  "success": false,
  "error": "Insufficient content credits",
  "code": "INSUFFICIENT_CREDITS",
  "required": 1,
  "available": 0
}

Frontend Handling

Balance Display

  • Header shows credit balances
  • Updates after each operation
  • Warning at low balance (< 10%)

Error Handling

// In writer store
async generateContent(taskId: string) {
  try {
    const response = await api.generateContent(taskId);
    // Update billing store
    billingStore.fetchBalance();
    return response;
  } catch (error) {
    if (error.code === 'INSUFFICIENT_CREDITS') {
      // Show upgrade modal
      uiStore.showUpgradeModal();
    }
    throw error;
  }
}

Usage Tracking

Usage Summary Endpoint

GET /api/v1/billing/usage/summary/?period=month

Response:

{
  "period": "2025-01",
  "usage": {
    "idea_credits": 45,
    "content_credits": 23,
    "image_credits": 67,
    "optimization_credits": 0
  },
  "by_operation": {
    "auto_cluster": 12,
    "generate_ideas": 33,
    "generate_content": 23,
    "generate_images": 67
  }
}

Automation Credit Estimation

Before running automation:

GET /api/v1/automation/estimate/?site_id=...

Response:

{
  "estimated_credits": {
    "idea_credits": 25,
    "content_credits": 10,
    "image_credits": 30
  },
  "stages": {
    "clustering": 5,
    "ideas": 20,
    "content": 10,
    "images": 30
  },
  "has_sufficient_credits": true
}

Credit Reset

Credits reset monthly based on billing cycle:

  1. Monthly Reset Job runs at period end
  2. Unused credits do not roll over
  3. Purchased credits may have different expiry

Celery Task

@celery.task
def reset_monthly_credits():
    """
    Run daily, resets credits for accounts
    whose period_end is today
    """
    today = date.today()
    balances = CreditBalance.objects.filter(period_end=today)
    
    for balance in balances:
        credit_service.reset_monthly_credits(balance.account)

Admin Operations

Manual Credit Adjustment

Via Django Admin or API:

# Add credits
credit_service.add_credits(
    account=account,
    credit_type='content',
    amount=100,
    reason='Customer support adjustment'
)

Usage Audit

All credit changes logged in CreditUsage with:

  • Timestamp
  • User who triggered
  • Operation type
  • Amount deducted
  • Related object ID