Overview
This webhook endpoint receives updates from the Telegram Bot API and handles all bot commands, messages, and callback queries. It processes subscription payments, manages MT5 copier setup, and controls access to the VIP channel.
Endpoint
POST /api/telegram/webhook
Request Body
The request body follows the Telegram Bot API Update object structure:
The update’s unique identifier
New incoming message of any kind Unique message identifier
Sender information Unique identifier for the user
User’s username (optional)
User’s last name (optional)
Text message content (for text messages)
New incoming callback query from inline keyboard buttons Show Callback Query properties
Unique identifier for this query
Sender information (same structure as message.from)
Data associated with the callback button
Supported Commands
User Commands
/start
/help
/pay
/verify_basic
/verify_biweekly
/verify_monthly
/verify_premium
/verify_promo
/status
/mt5setup
/settings
/mystats
/promo
Admin Commands
/broadcast
/broadcast_active
/broadcast_premium
/broadcast_promo
/botstats
/checkuser
/broadcast Your message here
Command Behaviors
/start
Displays welcome message with plan details and pricing information.
/pay
Initiates payment flow:
Prompts user for email address
Validates email format using regex: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
Generates payment links for all plans via /api/payment/link
Returns inline keyboard with payment buttons
/verify_* Commands
Verifies payment and grants access:
Rate Limiting : 3 failed attempts per user, then 1-hour block (configured in RATE_LIMIT.maxAttempts and RATE_LIMIT.blockDurationMs)
Verification Flow:
Check if reference is already being processed (idempotency)
Validate reference format (non-empty string)
Check for promo codes (EXTRA, EXTRA2, VIP, DISCOUNT)
Check custom promo codes in database
Verify transaction with Paystack API
Validate payment amount matches plan
Create subscription record
Generate and send invite link
For Premium plans: Auto-start MT5 setup flow
Promo Codes:
EXTRA - 1 week Premium + Meta Copier (FREE)
EXTRA2 - 2 weeks Premium + Meta Copier (FREE)
VIP - 1 week Basic (FREE)
DISCOUNT - 1 week Basic (₦3,000) - generates payment link
/status
Returns current subscription status including:
Plan type and name
Start and expiry dates
Days remaining
Copier access status
/mt5setup
Initiates MT5 copier setup flow (Premium only):
Requirements:
Active Premium subscription with hasCopierAccess: true
Cent account (not Standard)
Broker: Headway
Server: headway-real
Magic Number: 123456
Setup Flow:
Collect MT5 account number
Collect MT5 password (encrypted before storage)
Verify credentials with MetaCopier API
Create copier settings with defaults
/settings
Displays copier configuration menu with inline keyboard (Premium only):
Lot Size multiplier
Max Lot Size
Maximum Lot Total
Max Open Positions
Copy Stop Loss (on/off)
Copy Take Profit (on/off)
TP2 Enabled (on/off)
Callback Query Handlers
Inline keyboard buttons trigger callback queries with these data values:
Prompts user to enter Basic plan payment reference
Prompts user to enter Bi-Weekly plan payment reference
Prompts user to enter Monthly plan payment reference
Prompts user to enter Premium plan payment reference
Prompts user to enter Promo payment reference
Settings menu callbacks for copier configuration
Conversation State Management
The bot maintains conversation states for multi-step flows:
Email Collection State
Triggered by /pay command
Validates email format
Generates payment links after email submission
MT5 Setup State Machine
States:
account_number - Waiting for MT5 account number
password - Waiting for MT5 password
confirm_setup - Waiting for setup confirmation
Tracks users waiting to verify promo payments
Links expire after 48 hours (configured in PROMO_EXPIRY_HOURS)
Rate Limiting
Failed Verification Attempts : Users are blocked after 3 failed payment verification attempts. Block duration: 1 hour.
Rate limit implementation:
In-memory store: Map<userId, { count: number; blockedUntil: number }>
Max attempts: 3 (from RATE_LIMIT.maxAttempts)
Block duration: 3600000ms (1 hour)
Reset on successful verification
Idempotency
The webhook uses an in-memory Set to track references currently being processed, preventing duplicate subscription creation from concurrent requests.
const processingReferences = new Set < string >()
Response
The endpoint always returns 200 OK to acknowledge receipt of the update:
Telegram requires webhooks to respond within 60 seconds. This endpoint processes updates asynchronously and responds immediately.
Error Handling
Errors are communicated to users via Telegram messages, not HTTP responses:
User Errors
Rate Limited
Invalid Reference
Amount Mismatch
Already Used
No Premium Access
❌ Too many failed verification attempts. Please try again in 1 hour.
System Errors
Database Error
System Error
❌ Database Error
Failed to save your subscription. Please contact support.
Database Operations
The webhook performs these database operations:
Subscription Creation
await prisma . subscription . create ({
data: {
telegramUserId: string ,
telegramUsername: string ,
telegramName: string ,
paystackRef: string ,
customerEmail: string ,
amountKobo: number ,
planType: PlanType ,
hasCopierAccess: boolean ,
startedAt: Date ,
expiresAt: Date ,
inviteLinkUsed: string
}
})
MT5 Setup Creation
await prisma . mt5Setup . create ({
data: {
subscriptionId: string ,
accountNumber: string ,
accountPassword: string , // encrypted
copierMultiplier: number ,
lotSize: number ,
maxLotSize: number ,
maximumLot: number ,
maxOpenPositions: number ,
copyStopLoss: boolean ,
copyTakeProfit: boolean ,
tp2Enabled: boolean ,
setupStatus: 'active' | 'inactive'
}
})
Security Considerations
Password Encryption : MT5 passwords are encrypted using AES-256 before storage
Rate Limiting : Prevents brute force verification attempts
Idempotency : Prevents duplicate processing of same reference
Admin Verification : Admin commands check user.id === ADMIN_ID
Reference Validation : Checks for existing subscriptions with same reference
External API Calls
Telegram Bot API
Send Message
Create Invite Link
Unban User
await sendMessage ( userId , message )
Paystack API
await verifyTransaction ( reference )
await createMt5Account ( accountNumber , password )
await updateCopierSettings ( accountNumber , settings )
await removeUserMt5Account ( accountNumber )
Example Webhook Payloads
Text Message
Callback Query
{
"update_id" : 123456789 ,
"message" : {
"message_id" : 1234 ,
"from" : {
"id" : 987654321 ,
"is_bot" : false ,
"first_name" : "John" ,
"username" : "johndoe"
},
"chat" : {
"id" : 987654321 ,
"first_name" : "John" ,
"username" : "johndoe" ,
"type" : "private"
},
"date" : 1234567890 ,
"text" : "/start"
}
}