Promo codes allow you to offer special pricing, free trials, and limited-time promotions to boost subscriptions and reward loyal users.
The system supports two types of promo codes:
Hardcoded Promo Codes
Built into the source code for common scenarios:
EXTRA - 1 week Premium + Meta Copier (FREE)
EXTRA2 - 2 weeks Premium + Meta Copier (FREE)
VIP - 1 week Basic Only (FREE)
DISCOUNT - 1 week Basic for ₦3,000 (generates payment link)
Custom Database Promo Codes
Created dynamically with custom:
Plan types
Durations
Pricing
Usage limits
Expiration dates
These are immediately available without setup.
EXTRA (Premium 1 Week)
EXTRA2 (Premium 2 Weeks)
VIP (Basic 1 Week)
/promo EXTRA
✅ Grants: 1 week Premium + Auto Copier
💰 Cost: FREE
🔄 Usage: One-time per user
Free codes are perfect for influencer campaigns, referral rewards, or compensating users for issues.
/promo DISCOUNT
✅ Grants: 1 week Basic
💰 Cost: ₦3,000 (40% discount from ₦5,000 )
🔗 Generates: Payment link
When user enters DISCOUNT, they receive a payment button. After payment, subscription activates.
Create flexible, trackable promo codes stored in the database.
Admin users can create and manage promo codes directly via Telegram bot commands:
/create_promo Interactive 7-step wizard to create custom promo codes
/list_promos View all promo codes with usage statistics
/delete_promo CODE Delete a specific promo code by its code
The bot will guide you through 7 steps:
Promo Code - Code name (UPPERCASE, no spaces)
Display Name - Human-readable name
Plan Type - basic, biweekly, monthly, premium, or promo
Duration - Number of days (e.g., 7, 14, 30)
Free or Paid - Is it free or requires payment?
Amount - If paid, amount in Naira (e.g., 3000)
Copier Access - Premium MT5 copier included?
Expiry Date - When the promo code expires
Creating promos via bot is faster than using Prisma code and doesn’t require database access.
Shows all promo codes with:
Code name and display name
Plan details and duration
Usage count vs limit
Active/inactive status
Expiry date
/delete_promo NEWYEAR2025
Permanently removes the promo code from the database.
Deletion is irreversible. Users who already redeemed the code keep their subscriptions.
model PromoCode {
id String @id
code String @unique
name String ? // Display name
// Plan configuration
planType String // "basic", "premium", "biweekly", "monthly"
durationDays Int
hasCopierAccess Boolean @default ( false )
// Pricing
isFree Boolean @default ( false )
amountKobo Int ? // If not free
// Expiry
expiresAt DateTime
// Usage limits
usageLimit Int ? // Max total uses (null = unlimited)
usageCount Int @default ( 0 )
perUserLimit Int @default ( 1 )
// Metadata
createdBy String @default ( "admin" )
isActive Boolean @default ( true )
createdAt DateTime
updatedAt DateTime
}
Use Prisma to create promo codes:
await prisma . promoCode . create ({
data: {
code: 'NEWYEAR2025' ,
name: 'New Year Special 2025' ,
planType: 'monthly' ,
durationDays: 30 ,
hasCopierAccess: false ,
isFree: false ,
amountKobo: 1000000 , // ₦10,000
expiresAt: new Date ( '2025-01-31' ),
usageLimit: 100 ,
perUserLimit: 1 ,
isActive: true
}
})
Code must be UPPERCASE and unique. Duplicate codes will cause errors.
await prisma . promoCode . create ({
data: {
code: 'FREETRIAL' ,
name: 'Free 7-Day Trial' ,
planType: 'basic' ,
durationDays: 7 ,
hasCopierAccess: false ,
isFree: true ,
expiresAt: new Date ( '2025-12-31' ),
usageLimit: 500 ,
perUserLimit: 1 ,
isActive: true
}
})
Use case: Acquisition campaign to convert free users
Influencer Exclusive Offer
await prisma . promoCode . create ({
data: {
code: 'INFLUENCER50' ,
name: 'Influencer 50% Off' ,
planType: 'premium' ,
durationDays: 14 ,
hasCopierAccess: true ,
isFree: false ,
amountKobo: 1100000 , // ₦11,000 (50% off ₦22,000)
expiresAt: new Date ( '2025-06-30' ),
usageLimit: 50 ,
perUserLimit: 1 ,
isActive: true
}
})
Use case: Partner with influencer, track conversions
await prisma . promoCode . create ({
data: {
code: 'LOYAL30' ,
name: 'Loyalty Bonus - 30 Days' ,
planType: 'premium' ,
durationDays: 30 ,
hasCopierAccess: true ,
isFree: true ,
expiresAt: new Date ( '2025-03-31' ),
usageLimit: null , // Unlimited
perUserLimit: 1 ,
isActive: true
}
})
Use case: Reward users who made 3+ purchases
await prisma . promoCode . create ({
data: {
code: 'FLASH24' ,
name: '24-Hour Flash Sale' ,
planType: 'biweekly' ,
durationDays: 14 ,
hasCopierAccess: false ,
isFree: false ,
amountKobo: 700000 , // ₦7,000 (30% off ₦10,000)
expiresAt: new Date ( Date . now () + 24 * 60 * 60 * 1000 ), // 24 hours
usageLimit: 30 ,
perUserLimit: 1 ,
isActive: true
}
})
Use case: Urgency-driven conversion campaign
Send promotional offers to all users:
This command:
Creates a fresh payment link for ₦3,000 (7-day Basic plan)
Sends message to ALL users with payment button
Links expire after 48 hours
Includes “Verify Promo Payment” button
System Creates Links
Generates payment link with metadata: {
planType : 'promo' ,
metadata : {
broadcastTimestamp : Date . now (). toString ()
}
}
Users Receive Message
🔥 SPECIAL PROMO OFFER!
💎 LIMITED TIME: 7 Days for ONLY ₦3,000!
That's ₦2,000 OFF the regular Basic plan!
⚠️ Links expire in 48 hours
[🔥 Get ₦3,000 Promo (7 Days)]
[✅ Verify Promo Payment]
User Clicks & Pays
Payment link opens → User completes payment
User Verifies
Clicks “Verify Promo Payment” → Runs /verify_promo REFERENCE
Access Granted
Subscription created → Invite link sent
Promo Link Expiry:
Links expire 48 hours after broadcast
Each link works ONCE only
Users who click after expiry must wait for next broadcast
User Redemption Flow
How users redeem promo codes:
System Validates
Check if code exists (hardcoded or database)
Verify not expired (expiresAt > now)
Check usage limits not exceeded
Confirm user hasn’t used before
Create Subscription
await prisma . subscription . create ({
data: {
telegramUserId: user . id ,
paystackRef: promoCode , // Store code as reference
amountKobo: 0 , // Free
planType: 'premium' ,
hasCopierAccess: true ,
expiresAt: calculateExpiryDate ( 'premium' , currentExpiry )
}
})
Update Usage Count
await prisma . promoCode . update ({
where: { code: promoCode },
data: { usageCount: { increment: 1 } }
})
Grant Access
Send invite link or extend existing subscription
System Generates Payment Link
const response = await fetch ( '/api/payment/link' , {
method: 'POST' ,
body: JSON . stringify ({
telegramId: user . id ,
planType: 'custom' ,
metadata: { promoCode: 'DISCOUNT' }
})
})
User Receives Button
🎁 Special Offer!
✨ Get 7 Days for ₦3,000!
[🔥 Pay Now]
User Pays
Completes payment through Paystack
Access Granted
Subscription created with promo pricing
The system performs these checks:
1. Code Exists
const promo = await prisma . promoCode . findUnique ({
where: { code: promoCode . toUpperCase () }
})
if ( ! promo ) {
return 'Code not found'
}
2. Code Active
if ( ! promo . isActive ) {
return 'Code is inactive'
}
3. Not Expired
if ( new Date ( promo . expiresAt ) < new Date ()) {
return 'Code has expired'
}
4. Usage Limit
if ( promo . usageLimit && promo . usageCount >= promo . usageLimit ) {
return 'Code usage limit reached'
}
5. Per-User Limit
const userUsageCount = await prisma . subscription . count ({
where: {
telegramUserId: user . id ,
paystackRef: { equals: promoCode , mode: 'insensitive' }
}
})
if ( userUsageCount >= promo . perUserLimit ) {
return 'You already used this code'
}
All validation happens before creating subscription to prevent abuse.
const activeCodes = await prisma . promoCode . findMany ({
where: {
isActive: true ,
expiresAt: { gt: new Date () }
},
orderBy: { createdAt: 'desc' }
})
console . log ( 'Active Codes:' , activeCodes )
await prisma . promoCode . update ({
where: { code: 'OLDPROMO' },
data: { isActive: false }
})
Extend Expiration
await prisma . promoCode . update ({
where: { code: 'FLASH24' },
data: {
expiresAt: new Date ( '2025-12-31' )
}
})
Check Usage Stats
const promo = await prisma . promoCode . findUnique ({
where: { code: 'NEWYEAR2025' }
})
const remaining = promo . usageLimit
? promo . usageLimit - promo . usageCount
: 'Unlimited'
console . log ( `
Promo: ${ promo . name }
Used: ${ promo . usageCount }
Remaining: ${ remaining }
Expires: ${ promo . expiresAt . toLocaleDateString () }
` )
const topCodes = await prisma . promoCode . findMany ({
orderBy: { usageCount: 'desc' },
take: 10
})
topCodes . forEach (( code , i ) => {
console . log ( ` ${ i + 1 } . ${ code . code } : ${ code . usageCount } uses` )
})
Use Memorable Codes
WELCOME better than XYZ123
SUMMER2025 better than PROMO47
Short and easy to type
Set Clear Expiration
Use urgency: 24-72 hours for flash sales
Monthly campaigns: 30 days
Seasonal: End of season date
Limit Usage
First 50 users: Creates FOMO
One per user: Prevents abuse
Track performance by code
Test Before Launch
Create code in database
Test redemption yourself
Verify expiry and limits work
Track ROI
Monitor usageCount
Calculate revenue per code
Compare to acquisition cost
Communicate Clearly
Show savings amount (₦2,000 OFF)
Display expiration prominently
Include call-to-action
Seasonal Campaigns
NEWYEAR2025 - January special
BLACKFRIDAY - Black Friday sale
SUMMER50 - Summer 50% off
XMAS - Christmas promotion
Influencer Codes
JOHN20 - Influencer John’s 20% off
TRADER50 - Trading community discount
YOUTUBE100 - YouTube audience special
Milestone Codes
1000USERS - Celebrate 1000 users
LAUNCH - Product launch special
ANNIVERSARY - Annual celebration
Re-engagement
COMEBACK - Win-back churned users
MISSYOU - Inactive user offer
RETURN50 - 50% off for returners
Referral Rewards
FRIEND - Referral bonus
INVITE3 - Invite 3 friends reward
SHARE20 - Share and save