Integration Work
YeboLearn's integration ecosystem connects students, teachers, and parents with essential services. This document tracks active integration development and third-party service work.
Last Updated: November 22, 2025
Active Integrations
1. M-Pesa Payment Integration (Sprint 26 - In Progress)
Status: 40% Complete, On Track for Nov 29 Launch
Business Value:
- Primary payment method in Lesotho and Southern Africa
- Unlock $5/month subscriptions for students
- Reduce payment friction (no credit card needed)
- Enable mobile-first payments
- Market expansion opportunity
Integration Architecture:
YeboLearn Platform
├─ Student initiates payment
│ └─ Selects M-Pesa, enters phone number
├─ Backend creates payment request
│ ├─ Generates transaction ID
│ ├─ Calls M-Pesa API (STK Push)
│ └─ Stores pending transaction
├─ M-Pesa sends push to phone
│ └─ Student enters PIN
├─ M-Pesa processes payment
│ └─ Sends webhook callback
├─ YeboLearn receives callback
│ ├─ Verifies signature
│ ├─ Updates transaction status
│ ├─ Grants course access
│ └─ Sends confirmation email/SMS
└─ Student accesses paid contentTechnical Implementation:
// M-Pesa STK Push (Payment Initiation)
export async function initiatePayment(
phoneNumber: string,
amount: number,
courseId: string,
userId: string
): Promise<PaymentResponse> {
// Generate transaction ID
const transactionId = generateTransactionId();
// M-Pesa API credentials
const { consumerKey, consumerSecret, shortCode, passkey } = mpesaConfig;
// Get OAuth token
const token = await getOAuthToken(consumerKey, consumerSecret);
// Prepare STK Push request
const timestamp = generateTimestamp();
const password = generatePassword(shortCode, passkey, timestamp);
const response = await mpesaClient.stkPush({
BusinessShortCode: shortCode,
Password: password,
Timestamp: timestamp,
TransactionType: 'CustomerPayBillOnline',
Amount: amount,
PartyA: phoneNumber, // Customer phone
PartyB: shortCode, // Business shortcode
PhoneNumber: phoneNumber,
CallBackURL: `${API_URL}/webhooks/mpesa/callback`,
AccountReference: courseId,
TransactionDesc: `YeboLearn Course Payment`,
});
// Store pending transaction
await db.payment.create({
data: {
id: transactionId,
userId,
courseId,
amount,
currency: 'LSL', // Lesotho Loti
provider: 'mpesa',
status: 'pending',
phoneNumber,
mpesaCheckoutRequestId: response.CheckoutRequestID,
createdAt: new Date(),
},
});
return {
transactionId,
checkoutRequestId: response.CheckoutRequestID,
message: 'Check your phone to complete payment',
};
}
// M-Pesa Webhook Handler
export async function handleMpesaCallback(
callbackData: MpesaCallback
): Promise<void> {
// Verify callback signature
if (!verifySignature(callbackData)) {
throw new Error('Invalid callback signature');
}
const { Body } = callbackData;
const { ResultCode, ResultDesc, CheckoutRequestID } = Body.stkCallback;
// Find transaction
const payment = await db.payment.findUnique({
where: { mpesaCheckoutRequestId: CheckoutRequestID },
});
if (!payment) {
logger.error('Payment not found for checkout request', { CheckoutRequestID });
return;
}
// Update transaction status
if (ResultCode === 0) {
// Success
await db.payment.update({
where: { id: payment.id },
data: {
status: 'completed',
mpesaReceiptNumber: Body.stkCallback.CallbackMetadata.Item.find(
i => i.Name === 'MpesaReceiptNumber'
)?.Value,
completedAt: new Date(),
},
});
// Grant course access
await grantCourseAccess(payment.userId, payment.courseId);
// Send confirmation
await sendPaymentConfirmation(payment);
// Emit event for analytics
analytics.track('payment_completed', {
userId: payment.userId,
amount: payment.amount,
provider: 'mpesa',
});
} else {
// Failed
await db.payment.update({
where: { id: payment.id },
data: {
status: 'failed',
errorMessage: ResultDesc,
failedAt: new Date(),
},
});
// Notify user
await sendPaymentFailureNotification(payment, ResultDesc);
}
}Current Progress:
Completed (4 points):
- ✅ M-Pesa developer account and sandbox setup
- ✅ OAuth token generation and caching
- ✅ Payment initiation (STK Push) endpoint
- ✅ Basic error handling
In Progress (5 points):
- 🚧 Webhook callback handling (50% done)
- Signature verification complete
- Database updates in progress
- Testing callback scenarios
Not Started (4 points):
- ⏳ Error recovery and retry logic
- Handle timeout scenarios
- Retry failed callbacks
- Manual reconciliation
- ⏳ Payment status dashboard
- Admin view of all transactions
- Filter and search
- Export capabilities
Testing Strategy:
// Integration tests with M-Pesa sandbox
describe('M-Pesa Integration', () => {
it('should initiate payment successfully', async () => {
const response = await initiatePayment(
'+26878422613', // Test number
500, // LSL 500 (~$25)
'course-123',
'user-456'
);
expect(response.checkoutRequestId).toBeDefined();
expect(response.message).toContain('Check your phone');
});
it('should handle successful payment callback', async () => {
const callback = mockSuccessfulCallback();
await handleMpesaCallback(callback);
const payment = await db.payment.findUnique({
where: { id: 'txn-123' },
});
expect(payment.status).toBe('completed');
const enrollment = await db.enrollment.findFirst({
where: {
userId: 'user-456',
courseId: 'course-123',
},
});
expect(enrollment).toBeDefined();
});
it('should handle failed payment callback', async () => {
const callback = mockFailedCallback('Insufficient funds');
await handleMpesaCallback(callback);
const payment = await db.payment.findUnique({
where: { id: 'txn-123' },
});
expect(payment.status).toBe('failed');
expect(payment.errorMessage).toContain('Insufficient funds');
});
});Beta Launch Plan:
Week 1 (Nov 29 - Dec 5): Limited Beta
- 10 test users with real accounts
- Small amounts (LSL 50-100)
- Monitor closely for issues
- Collect feedback
Week 2 (Dec 6-12): Expanded Beta
- 50 users
- Full subscription prices (LSL 500/month)
- Performance monitoring
- Support team trained
Week 3+ (Dec 13+): General Availability
- All users can pay via M-Pesa
- Marketing campaign launches
- Monitor payment success rate (target: >95%)Risk Mitigation:
Risk: Production credentials delayed
Mitigation: Can launch beta on sandbox, switch to prod later
Risk: Payment failures due to network
Mitigation: Retry logic, manual reconciliation dashboard
Risk: Webhook not received
Mitigation: Polling backup (check status every 30s for 5 min)
Risk: Duplicate payments
Mitigation: Idempotency keys (Sprint 26 technical debt work)2. WhatsApp Business API Integration (Sprint 27 - Planned)
Status: Planning Phase, API Access Requested
Business Value:
- Reach students where they are (WhatsApp ubiquitous in Africa)
- Notification delivery (better than email)
- Two-way communication (support, reminders)
- Course enrollment via WhatsApp
- Low-bandwidth option for rural students
Use Cases:
1. Notifications
Quiz Reminder:
"Hi Sarah! 👋 You have a quiz due tomorrow in Mathematics 101.
Complete it before 11:59 PM to stay on track. Good luck! 📚"
Grade Available:
"Your essay on Climate Change has been graded! 🎉
Score: 85% with detailed AI feedback. View your results: [link]"
Course Enrollment:
"Welcome to Biology 201! 🧬 Your course starts Monday.
Access materials: [link]
Need help? Reply to this message."2. Interactive Bot
Student: "What's my progress in Math?"
Bot: "You're 65% through Math 101!
- Completed: 13/20 quizzes
- Average score: 78%
- Next topic: Quadratic Equations
Keep it up! 💪"
Student: "When is my next quiz due?"
Bot: "Your next quiz is Chemistry Chapter 5, due Friday 5 PM.
Would you like to start it now? (Yes/No)"
Student: "Yes"
Bot: "Opening quiz... [link to quiz]"Technical Architecture:
WhatsApp Cloud API
├─ YeboLearn Backend
│ ├─ Webhook receiver
│ ├─ Message handler
│ ├─ Business logic router
│ └─ Response generator
├─ Message Templates
│ ├─ Quiz reminders
│ ├─ Grade notifications
│ ├─ Course updates
│ └─ Payment confirmations
└─ Interactive Features
├─ Quick replies
├─ List messages
├─ Button messages
└─ Rich media (images, docs)Implementation Plan (Sprint 27-28):
Sprint 27 (8 points):
- [ ] WhatsApp Business API setup and verification
- [ ] Webhook endpoint for incoming messages
- [ ] Notification templates (quiz, grades, enrollment)
- [ ] Send notification implementation
- [ ] Basic testing
Features:
- One-way notifications only
- No interactive bot yet
- Manual trigger for testingSprint 28 (13 points):
- [ ] Interactive bot logic
- [ ] Natural language understanding (NLU)
- [ ] Command parsing ("my progress", "next quiz")
- [ ] Integration with student data
- [ ] Full testing and beta launch
Features:
- Two-way conversations
- Student queries
- Course information
- Progress trackingMessage Templates:
// WhatsApp notification templates
export const templates = {
quizReminder: {
name: 'quiz_reminder',
language: 'en',
components: [
{
type: 'body',
parameters: [
{ type: 'text', text: '{{studentName}}' },
{ type: 'text', text: '{{quizName}}' },
{ type: 'text', text: '{{dueDate}}' },
],
},
],
},
gradeAvailable: {
name: 'grade_available',
language: 'en',
components: [
{
type: 'body',
parameters: [
{ type: 'text', text: '{{assignmentName}}' },
{ type: 'text', text: '{{score}}' },
],
},
{
type: 'button',
sub_type: 'url',
index: '0',
parameters: [
{ type: 'text', text: '{{viewResultsUrl}}' },
],
},
],
},
};
// Send notification
async function sendWhatsAppNotification(
phoneNumber: string,
template: string,
parameters: any[]
) {
await whatsappClient.sendMessage({
messaging_product: 'whatsapp',
to: phoneNumber,
type: 'template',
template: {
name: template,
language: { code: 'en' },
components: [
{
type: 'body',
parameters,
},
],
},
});
}Compliance and Privacy:
WhatsApp Business Policy Compliance:
✓ No spam (only opt-in users)
✓ No promotional content (education only)
✓ Clear opt-out mechanism
✓ Privacy policy updated
✓ Data protection (no sensitive info in messages)
User Opt-In Flow:
1. Student enables WhatsApp notifications in settings
2. Verify phone number (SMS code)
3. Send welcome message
4. Confirm preferences (quizzes, grades, courses)
5. Allow granular control (turn off specific types)
Opt-Out Flow:
1. Reply "STOP" to any message
2. Or disable in settings
3. Immediate effect (within 5 minutes)3. Google Gemini AI (Ongoing)
Status: Production, Continuous Optimization
Current Usage:
Active Features:
✓ Quiz generation (Gemini 1.5 Flash)
✓ Essay grading (Gemini 1.5 Pro)
✓ Content recommendations (Gemini 1.5 Flash)
✓ Study planner (Gemini 1.5 Pro) - Sprint 27
Usage Stats (November 2025):
- API calls: ~12,000/day
- Input tokens: 125M/month
- Output tokens: 48M/month
- Cost: ~$200/month
- Error rate: 1.2%See AI Features Documentation for detailed Gemini integration work.
4. Email Service (SendGrid) (Production)
Status: Stable, Minor Improvements Planned
Current Integration:
// Transactional emails
export async function sendEmail(
to: string,
template: string,
data: any
) {
await sendGridClient.send({
to,
from: '[email protected]',
templateId: templates[template],
dynamicTemplateData: data,
});
}
// Email templates
const emailTemplates = {
welcome: 'd-123456',
quizReminder: 'd-234567',
gradeAvailable: 'd-345678',
paymentConfirmation: 'd-456789',
passwordReset: 'd-567890',
};
// Usage
await sendEmail(
'[email protected]',
'gradeAvailable',
{
studentName: 'Sarah',
assignmentName: 'Climate Change Essay',
score: 85,
viewUrl: 'https://yebolearn.app/grades/123',
}
);Email Performance:
Delivery Rate: 98.5% (excellent)
Open Rate: 42% (above average)
Click Rate: 18% (good)
Bounce Rate: 1.2% (low)
Spam Reports: 0.1% (very low)
Volume:
- Daily: ~2,500 emails
- Monthly: ~75,000 emails
- Cost: $45/monthImprovements Planned (Sprint 28):
- [ ] Email preference center (granular control)
- [ ] Unsubscribe management (better UX)
- [ ] A/B testing framework
- [ ] Email analytics dashboard
- [ ] Localization (Sesotho translations)
Effort: 3 story points5. SMS Service (Twilio) (Production)
Status: Stable, Low Usage
Current Usage:
Use Cases:
✓ Phone verification (signup, phone change)
✓ Password reset (2FA)
✓ Critical notifications (payment failures)
Volume:
- Daily: ~50 SMS
- Monthly: ~1,500 SMS
- Cost: $30/month
Delivery Rate: 99.2%Implementation:
// Send SMS
export async function sendSMS(
phoneNumber: string,
message: string
) {
await twilioClient.messages.create({
to: phoneNumber,
from: '+26612345678', // Twilio number
body: message,
});
}
// Use cases
await sendSMS(
'+26878422613',
'Your YeboLearn verification code is: 123456'
);
await sendSMS(
'+26878422613',
'Payment failed: Insufficient funds. Please try again.'
);Future Enhancement:
Replace Twilio SMS with WhatsApp (Sprint 28+)
- Lower cost (WhatsApp: $0.005 vs SMS: $0.02)
- Better delivery (WhatsApp more reliable)
- Richer content (buttons, links)
- Two-way communication6. Google Cloud Storage (Production)
Status: Stable, Minor Optimizations
Current Usage:
Storage Buckets:
├─ yebolearn-uploads (user content)
│ ├─ Essay submissions
│ ├─ Profile pictures
│ └─ Course materials
├─ yebolearn-assets (static assets)
│ ├─ Images, videos
│ ├─ PDFs, documents
│ └─ Thumbnails
└─ yebolearn-backups (database backups)
└─ Daily automated backups
Storage Size: 45 GB
Monthly Cost: $9Optimization (Sprint 27):
Current: All files in single bucket
Problem: No CDN, slow for international users
Improvement: Cloud CDN integration
- Cache static assets at edge locations
- Faster delivery (200ms → 50ms in South Africa)
- Lower egress costs
- Better user experience
Effort: 2 story points
Cost: +$5/month (offset by egress savings)API Improvements
Public API (Beta - Sprint 28)
Status: Planning Phase
Business Value:
- Partner integrations (schools, LMS)
- Third-party app ecosystem
- Data export for students
- Platform extensibility
Planned Endpoints:
Authentication:
POST /api/v1/auth/token - OAuth2 token
Courses:
GET /api/v1/courses - List courses
GET /api/v1/courses/:id - Course details
POST /api/v1/enrollments - Enroll student
Progress:
GET /api/v1/students/:id/progress - Student progress
GET /api/v1/students/:id/grades - Grades
Quizzes:
GET /api/v1/quizzes/:id - Quiz details
POST /api/v1/quiz-attempts - Submit quiz
AI Features:
POST /api/v1/ai/generate-quiz - Generate quiz (rate limited)
POST /api/v1/ai/grade-essay - Grade essay (rate limited)API Design:
// RESTful, JSON API
GET /api/v1/courses?page=1&limit=20
Response:
{
"data": [
{
"id": "course-123",
"title": "Mathematics 101",
"description": "Introduction to algebra",
"thumbnail": "https://cdn.yebolearn.app/...",
"instructor": {
"id": "teacher-456",
"name": "Mr. Johnson"
},
"enrollment_count": 340,
"rating": 4.7
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 156,
"total_pages": 8
},
"links": {
"self": "/api/v1/courses?page=1",
"next": "/api/v1/courses?page=2",
"last": "/api/v1/courses?page=8"
}
}Rate Limiting:
Free Tier:
- 1,000 requests/hour
- 10,000 requests/day
- No AI endpoints
Partner Tier ($99/month):
- 10,000 requests/hour
- 100,000 requests/day
- AI endpoints (limited)
Enterprise Tier (custom):
- Custom limits
- Dedicated support
- SLA guaranteesDocumentation:
Tools:
- OpenAPI/Swagger specification
- Interactive API explorer
- Code examples (JavaScript, Python, PHP)
- Postman collection
- SDKs (JavaScript, Python)
Docs Site: developers.yebolearn.appSprint 28 Scope (8 points):
- [ ] API authentication (OAuth2)
- [ ] Core endpoints (courses, progress)
- [ ] Rate limiting middleware
- [ ] API documentation (Swagger)
- [ ] Beta partner onboarding
Not in scope:
- AI endpoints (Sprint 29)
- SDKs (Sprint 30)
- Enterprise features (Q2)Integration Health
Monitoring
Integration Uptime (Last 30 Days):
- M-Pesa: N/A (not launched)
- WhatsApp: N/A (not launched)
- Gemini AI: 99.8%
- SendGrid: 99.9%
- Twilio: 99.5%
- Cloud Storage: 99.99%
Error Rates:
- Gemini AI: 1.2% (mostly rate limits)
- SendGrid: 0.3% (invalid emails)
- Twilio: 0.5% (invalid numbers)Cost Tracking
November 2025 Integration Costs:
- Gemini AI: $200
- SendGrid: $45
- Twilio: $30
- Cloud Storage: $9
- Other: $16
Total: $300/month
Per Student Cost: $0.13/month
Revenue per Student: $5/month
Margin: 97.4% 💰Related Documentation
- Current Work Overview - Sprint status
- AI Features - AI development details
- Platform Improvements - Infrastructure work
- Technical Architecture - System design