UNPKG

@jokoor/sdk

Version:
447 lines (358 loc) 12.3 kB
# Jokoor SMS SDK for TypeScript/JavaScript Official TypeScript/JavaScript SDK for the Jokoor SMS API. This SDK provides a simple and type-safe way to integrate Jokoor's SMS services into your applications. ## Features - 🔐 **API Key Authentication** - Support for live modes only (SMS does not support test modes) - 📱 **SMS Services** - Send individual or bulk SMS messages - 📊 **Campaign Management** - Create and manage SMS campaigns - 📝 **Template Management** - Create reusable message templates with variables - 👥 **Contact Management** - Organize contacts and contact groups - 🚀 **TypeScript Support** - Full type safety and IntelliSense - ⚡ **Automatic Retries** - Built-in retry logic with exponential backoff - 🛡️ **Result Pattern** - Type-safe `{data, error}` pattern for all API calls (no exceptions thrown) ## Installation ```bash npm install @jokoor/sdk # or yarn add @jokoor/sdk # or pnpm add @jokoor/sdk ``` ## Quick Start ```typescript import { Jokoor } from '@jokoor/sdk'; const jokoor = new Jokoor('sk_live_your_api_key_here'); // Send an SMS - returns {data, error} instead of throwing const { data: sms, error } = await jokoor.sms.send({ to: '+2207123456', message: 'Hello from Jokoor!' }); if (error) { console.error('Failed to send SMS:', error); } else { console.log('SMS sent:', sms.id); } // Create a campaign const { data: campaign, error: campaignError } = await jokoor.campaigns.create({ name: 'Summer Sale', message: 'Get 20% off all items this weekend!', contactGroupIds: ['grp_123'] }); if (campaignError) { console.error('Failed to create campaign:', campaignError); return; } // Send the campaign const { error: sendError } = await jokoor.campaigns.send(campaign.id); if (sendError) { console.error('Failed to send campaign:', sendError); } else { console.log('Campaign sent successfully'); } ``` ## Configuration ```typescript const jokoor = new Jokoor('sk_live_your_api_key_here', { baseURL: 'https://api.jokoor.com', // Optional (default) timeout: 30000, // Optional, in milliseconds maxRetries: 3, // Optional debug: false // Optional, enables debug logging }); ``` ## Template Variable System ### Overview Jokoor's template system supports two types of variables for creating dynamic messages: 1. **Contact Fields** - Personalized per recipient 2. **Template Parameters** - Static values for all recipients ### Contact Fields (Dynamic Personalization) Only these 3 fields are personalized per recipient: - `{{first_name}}` or `{{firstName}}` - Contact's first name - `{{last_name}}` or `{{lastName}}` - Contact's last name - `{{email}}` - Contact's email address ### Template Parameters (Static Values) All other variables remain the same for all recipients: - Business data: `{{company_name}}`, `{{store_location}}` - Promotional codes: `{{promo_code}}`, `{{discount}}` - Dates/times: `{{event_date}}`, `{{expires_at}}` - Any custom variable: `{{custom_field}}` ### How It Works ```typescript // Template: "Hi {{first_name}}, enjoy {{discount}}% off with code {{promo_code}}!" const campaign = await jokoor.campaigns.create({ name: 'Weekend Sale', templateId: 'promo_template', templateParams: { first_name: 'Valued Customer', // Fallback if contact has no first_name discount: '20', // Static - same for all recipients promo_code: 'WEEKEND20' // Static - same for all recipients }, contactGroupIds: ['all_customers'] }); // Results: // John Doe → "Hi John, enjoy 20% off with code WEEKEND20!" // Jane Smith → "Hi Jane, enjoy 20% off with code WEEKEND20!" // Contact without name → "Hi Valued Customer, enjoy 20% off with code WEEKEND20!" ``` ### Important Notes - **Automatic Personalization**: The system automatically checks if phone numbers belong to contacts - **Priority Rules**: Contact field values always override template parameters for contacts - **Fallback Support**: Always provide fallback values for contact fields in templateParams ## Core API Usage ### SMS Operations ```typescript // Send simple SMS const sms = await jokoor.sms.send({ to: '+2207123456', message: 'Your verification code is: 123456' }); // Send scheduled SMS const scheduledSMS = await jokoor.sms.send({ to: '+2207123456', message: 'Reminder: Your appointment is tomorrow', scheduledAt: '2024-01-20T10:00:00Z' }); // Send SMS with template const templatedSMS = await jokoor.sms.send({ to: '+2207123456', templateId: 'tpl_welcome', templateParams: { firstName: 'John', code: '123456' } }); // Get SMS status const status = await jokoor.sms.get('sms_123'); // List SMS messages const messages = await jokoor.sms.list({ limit: 50, status: 'sent' }); ``` ### Campaign Management ```typescript // Create campaign with direct message const campaign = await jokoor.campaigns.create({ name: 'Holiday Greetings', message: 'Season\'s greetings from {{company_name}}!', contactGroupIds: ['grp_customers'], templateParams: { company_name: 'Jokoor Inc.' } }); // Create campaign with template const templateCampaign = await jokoor.campaigns.create({ name: 'Welcome Series', templateId: 'tpl_welcome', contactIds: ['contact_123', 'contact_456'], templateParams: { first_name: 'Valued Customer', // Fallback discount_code: 'WELCOME10' } }); // Send campaign await jokoor.campaigns.send(campaign.id); // Get campaign statistics const stats = await jokoor.campaigns.getStats(campaign.id); console.log(`Sent: ${stats.data.details.totalSentMessages}`); ``` ### Template Management ```typescript // Create template const templateResult = await jokoor.templates.create({ name: 'welcome_message', body: 'Welcome {{firstName}}! Your code is {{code}}.' }); if (templateResult.error) { console.error('Failed to create template:', templateResult.error); return; } // Update template const updateResult = await jokoor.templates.update(templateResult.data.id, { body: 'Hi {{first_name}}! Your code is {{code}}. Valid for {{validity}} minutes.' }); if (updateResult.data) { console.log('Template updated successfully'); } // List templates const listResult = await jokoor.templates.list(); if (listResult.data) { console.log(`Found ${listResult.data.count} templates`); } ``` ### Contact Management ```typescript // Create contact const contact = await jokoor.contacts.create({ phoneNumber: '+2207123456', firstName: 'John', lastName: 'Doe', email: 'john@example.com' }); // Update contact await jokoor.contacts.update(contact.id, { email: 'john.doe@example.com' }); // Search contacts const contacts = await jokoor.contacts.list({ search: 'john' }); ``` ### Contact Groups ```typescript // Create group const group = await jokoor.contactGroups.create({ name: 'VIP Customers', description: 'Premium tier customers' }); // Add contacts to group await jokoor.contactGroups.addContacts(group.id, [ 'contact_123', 'contact_456' ]); // Remove contacts from group await jokoor.contactGroups.removeContacts(group.id, [ 'contact_456' ]); ``` ## Error Handling The SDK uses a Result pattern - all methods return `{data, error}` instead of throwing exceptions. This makes error handling explicit and type-safe. ```typescript // All API calls return a Result type - destructure for clean code const { data, error } = await jokoor.sms.send({ to: 'invalid-number', message: 'Test' }); if (error) { // Error is always a string console.error('API Error:', error); // Example errors: // "Invalid phone number format" // "Insufficient balance" // "Rate limit exceeded" // "Authentication failed" // "Resource not found" // "Service temporarily unavailable" } else { // TypeScript knows data is available here console.log('SMS sent:', data.id); } // You can also rename while destructuring const { data: sms, error: smsError } = await jokoor.sms.send({ to: '+2207123456', message: 'Hello!' }); ``` ### Result Type Utilities The SDK exports helpful utilities for working with Results: ```typescript import { isOk, isErr, unwrap, unwrapOr, map, chain } from '@jokoor/sdk'; // Check if successful if (isOk(result)) { console.log(result.data); // TypeScript knows data exists } // Check if error if (isErr(result)) { console.error(result.error); // TypeScript knows error exists } // Extract data or throw (for migration from try-catch) try { const data = unwrap(result); } catch (e) { console.error(e.message); } // Extract data or use default const data = unwrapOr(result, { id: 'default' }); // Transform successful results const idResult = map(result, sms => sms.id); // Chain operations const chainedResult = await chain( await jokoor.sms.send({ to: '+123', message: 'Hi' }), async (sms) => await jokoor.sms.get(sms.id) ); ``` ### Common Error Messages - **Authentication**: "Authentication failed", "Invalid API key" - **Validation**: "Invalid phone number format", "Message body is required" - **Resources**: "Resource not found", "Contact group not found" - **Limits**: "Rate limit exceeded", "Insufficient balance" - **Network**: "Unable to connect to API server", "Request timed out" - **Server**: "Internal server error", "Service temporarily unavailable" ## TypeScript Support Full type definitions for all methods and responses: ```typescript import { Jokoor, JokoorConfig, Result, // Request Types SMSSendParams, CampaignCreateParams, ContactCreateParams, TemplateCreateParams, // Response Types SMSResponse, CampaignResponse, ContactResponse, TemplateResponse, // Utility Types PaginatedResponse, CampaignStats } from '@jokoor/sdk'; ``` ## API Reference ### SMS (`jokoor.sms`) - `send(params)` - Send an SMS message - `get(id)` - Get SMS details - `list(options?)` - List SMS messages - `resend(id)` - Resend failed SMS - `resendBatch(ids)` - Resend multiple failed messages - `sendDraft(id, scheduledAt?)` - Send draft SMS ### Campaigns (`jokoor.campaigns`) - `create(params)` - Create SMS campaign - `get(id)` - Get campaign details - `update(id, params)` - Update campaign - `delete(id)` - Delete campaign - `list(options?)` - List campaigns - `send(id)` - Send campaign - `getStats(id)` - Get campaign statistics - `getMessages(id, options?)` - Get campaign messages - `resendFailed(id)` - Resend failed messages ### Templates (`jokoor.templates`) - `create(params)` - Create SMS template - `get(id)` - Get template details - `update(id, params)` - Update template - `delete(id)` - Delete template - `list(options?)` - List templates ### Contacts (`jokoor.contacts`) - `create(params)` - Create contact - `get(id)` - Get contact details - `update(id, params)` - Update contact - `delete(id)` - Delete contact - `list(options?)` - List contacts ### Contact Groups (`jokoor.contactGroups`) - `create(params)` - Create contact group - `get(id)` - Get group details - `update(id, params)` - Update group - `delete(id)` - Delete group - `list(options?)` - List groups - `addContacts(id, contactIds)` - Add contacts to group - `removeContacts(id, contactIds)` - Remove contacts from group ## Best Practices 1. **API Key Security**: Never expose your secret API key in client-side code 2. **Template Variables**: Always provide fallback values for contact fields 3. **Error Handling**: Wrap API calls in try-catch blocks 4. **Bulk Operations**: Use campaigns for sending to multiple recipients 5. **Contact Organization**: Use groups for better campaign targeting 6. **Rate Limiting**: Implement appropriate backoff strategies ## Documentation For comprehensive guides and examples: - 📚 [Full SDK Documentation](./docs/README.md) - 📖 [Template Variable Guide](./docs/guides/templates/variable-rules.md) - 🚀 [Quick Start Guide](./docs/getting-started/quick-start.md) - 💡 [SMS Best Practices](./docs/guides/sms/sending-sms.md) - 🎯 [Campaign Examples](./docs/guides/campaigns/creating.md) ## Support - 📧 Email: hello@jokoor.com - 📚 REST API Documentation: https://developers.jokoor.com - 🐛 Issues: https://github.com/jokoor/sdk-typescript/issues ## License MIT License - see LICENSE file for details