Developer

Bulk SMS API Integration Tutorial

BulkSMS Nigeria Team
15 min read
Updated Jan 25, 2025

Introduction

Integrating SMS functionality into your application unlocks powerful capabilities: send OTPs for authentication, notify customers of order updates, deliver marketing campaigns programmatically, and automate critical alerts. Our REST API makes it simple to send SMS from any application, whether you're building with PHP, Python, JavaScript, or any language that supports HTTP requests.

This comprehensive tutorial walks you through integrating the BulkSMS Nigeria API step-by-step, from authentication to sending your first message, handling responses, and implementing best practices. By the end, you'll have a fully functional SMS integration ready for production use.

What You'll Learn

  • β€’ How to authenticate with the API using your credentials
  • β€’ Sending single and bulk SMS messages
  • β€’ Checking account balance and delivery reports
  • β€’ Error handling and response codes
  • β€’ Code examples in PHP, Python, JavaScript, Node.js, and cURL
  • β€’ Best practices for production deployments

Prerequisites

What You Need Before Starting

  • BulkSMS Nigeria Account: Sign up free to get your API credentials
  • API Token: Found in your dashboard under Settings β†’ API Configuration
  • SMS Credits: Purchase credits or use free trial credits (50 SMS)
  • Development Environment: PHP 7.4+, Python 3.7+, Node.js 14+, or any HTTP client
  • Basic Programming Knowledge: Understanding of HTTP requests, JSON, and your chosen language

API Overview

API Specifications:

  • Base URL: https://www.bulksmsnigeria.com/api/v2
  • Protocol: HTTPS (TLS 1.2+)
  • Authentication: API Token (Bearer authentication)
  • Request Format: JSON or Form Data
  • Response Format: JSON
  • Rate Limit: 100 requests per minute
  • Character Encoding: UTF-8

Step 1: Get Your API Credentials

Finding Your API Token

  1. Log in to your dashboard: https://www.bulksmsnigeria.com/login
  2. Navigate to Settings: Click "Settings" or "API Configuration" in the menu
  3. Copy your API Token: You'll see a long string like abc123xyz789...
  4. Keep it secure: Treat your API token like a passwordβ€”never expose it in client-side code or public repositories

Security Warning

Your API token grants full access to your account. Store it in environment variables or secure configuration files, never hardcode it in your source code. Rotate tokens periodically and immediately if compromised.

Step 2: Send Your First SMS

Quick Start Example (cURL)

Let's send a test SMS using cURL to understand the basic request structure:

curl -X POST https://www.bulksmsnigeria.com/api/v2/sms \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "sender": "YourBrand",
    "message": "Hello! This is a test message from BulkSMS Nigeria API.",
    "recipients": "2348012345678"
  }'

Replace YOUR_API_TOKEN with your actual token and 2348012345678 with a valid Nigerian phone number.

Expected Response

{
  "status": "success",
  "message": "Message sent successfully",
  "data": {
    "message_id": "msg_abc123xyz789",
    "total_recipients": 1,
    "total_cost": 6.00,
    "balance_after": 494.00,
    "recipients": [
      {
        "phone": "2348012345678",
        "status": "queued",
        "message_id": "msg_abc123xyz789_001"
      }
    ]
  }
}

Step 3: Integration by Language

Choose your programming language and follow the implementation guide:

PHP Integration

Using PHP cURL (Vanilla PHP)

<?php

class BulkSMSNigeria {
    private $apiToken;
    private $baseUrl = 'https://www.bulksmsnigeria.com/api/v2';

    public function __construct($apiToken) {
        $this->apiToken = $apiToken;
    }

    public function sendSMS($sender, $message, $recipients) {
        $url = $this->baseUrl . '/sms';

        // Prepare data
        $data = [
            'sender' => $sender,
            'message' => $message,
            'recipients' => $recipients
        ];

        // Initialize cURL
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $this->apiToken,
            'Content-Type: application/json',
            'Accept: application/json'
        ]);

        // Execute request
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        // Parse response
        $result = json_decode($response, true);

        if ($httpCode === 200 && $result['status'] === 'success') {
            return $result;
        } else {
            throw new Exception($result['message'] ?? 'SMS sending failed');
        }
    }

    public function getBalance() {
        $url = $this->baseUrl . '/balance';

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $this->apiToken,
            'Accept: application/json'
        ]);

        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true);
    }
}

// Usage Example
try {
    $sms = new BulkSMSNigeria('YOUR_API_TOKEN');

    $result = $sms->sendSMS(
        'YourBrand',                    // Sender ID
        'Hello from PHP!',               // Message
        '2348012345678'                  // Recipient(s)
    );

    echo "Message sent! ID: " . $result['data']['message_id'];
    echo "\nCost: ₦" . $result['data']['total_cost'];
    echo "\nBalance: ₦" . $result['data']['balance_after'];

} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

?>

Using PHP with Guzzle HTTP Client

<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

class BulkSMSClient {
    private $client;

    public function __construct($apiToken) {
        $this->client = new Client([
            'base_uri' => 'https://www.bulksmsnigeria.com/api/v2/',
            'headers' => [
                'Authorization' => 'Bearer ' . $apiToken,
                'Content-Type' => 'application/json',
                'Accept' => 'application/json'
            ],
            'timeout' => 30
        ]);
    }

    public function sendSMS($sender, $message, $recipients) {
        try {
            $response = $this->client->post('sms', [
                'json' => [
                    'sender' => $sender,
                    'message' => $message,
                    'recipients' => $recipients
                ]
            ]);

            return json_decode($response->getBody(), true);

        } catch (RequestException $e) {
            if ($e->hasResponse()) {
                $error = json_decode($e->getResponse()->getBody(), true);
                throw new Exception($error['message'] ?? 'Request failed');
            }
            throw $e;
        }
    }
}

// Usage
$sms = new BulkSMSClient('YOUR_API_TOKEN');
$result = $sms->sendSMS('YourBrand', 'Hello from Guzzle!', '2348012345678');
print_r($result);

?>

Python Integration

Using Python Requests Library

import requests
import json

class BulkSMSNigeria:
    def __init__(self, api_token):
        self.api_token = api_token
        self.base_url = 'https://www.bulksmsnigeria.com/api/v2'
        self.headers = {
            'Authorization': f'Bearer {api_token}',
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }

    def send_sms(self, sender, message, recipients):
        """
        Send SMS to one or more recipients

        Args:
            sender (str): Sender ID (max 11 characters)
            message (str): Message content
            recipients (str or list): Phone number(s) - can be string or list

        Returns:
            dict: API response with message ID, cost, etc.
        """
        url = f'{self.base_url}/sms'

        # Convert list to comma-separated string if needed
        if isinstance(recipients, list):
            recipients = ','.join(recipients)

        payload = {
            'sender': sender,
            'message': message,
            'recipients': recipients
        }

        try:
            response = requests.post(
                url,
                headers=self.headers,
                json=payload,
                timeout=30
            )
            response.raise_for_status()
            return response.json()

        except requests.exceptions.HTTPError as e:
            error_data = e.response.json() if e.response else {}
            raise Exception(error_data.get('message', 'SMS sending failed'))

        except requests.exceptions.RequestException as e:
            raise Exception(f'Network error: {str(e)}')

    def get_balance(self):
        """Get current account balance"""
        url = f'{self.base_url}/balance'

        try:
            response = requests.get(url, headers=self.headers, timeout=10)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            raise Exception(f'Failed to get balance: {str(e)}')

    def get_delivery_report(self, message_id):
        """Get delivery report for a specific message"""
        url = f'{self.base_url}/delivery/{message_id}'

        try:
            response = requests.get(url, headers=self.headers, timeout=10)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            raise Exception(f'Failed to get delivery report: {str(e)}')


# Usage Example
if __name__ == '__main__':
    # Initialize client
    sms = BulkSMSNigeria('YOUR_API_TOKEN')

    try:
        # Send single SMS
        result = sms.send_sms(
            sender='YourBrand',
            message='Hello from Python! This is a test message.',
            recipients='2348012345678'
        )

        print(f"βœ“ Message sent successfully!")
        print(f"  Message ID: {result['data']['message_id']}")
        print(f"  Cost: ₦{result['data']['total_cost']}")
        print(f"  Balance: ₦{result['data']['balance_after']}")

        # Send to multiple recipients
        bulk_result = sms.send_sms(
            sender='YourBrand',
            message='Bulk message to multiple recipients',
            recipients=['2348012345678', '2348087654321', '2349012345678']
        )

        print(f"\nβœ“ Bulk message sent to {bulk_result['data']['total_recipients']} recipients")

        # Check balance
        balance = sms.get_balance()
        print(f"\nCurrent Balance: ₦{balance['data']['balance']}")

    except Exception as e:
        print(f"βœ— Error: {e}")

JavaScript (Node.js) Integration

Using Axios Library

const axios = require('axios');

class BulkSMSNigeria {
    constructor(apiToken) {
        this.apiToken = apiToken;
        this.baseUrl = 'https://www.bulksmsnigeria.com/api/v2';
        this.client = axios.create({
            baseURL: this.baseUrl,
            headers: {
                'Authorization': `Bearer ${apiToken}`,
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            },
            timeout: 30000
        });
    }

    async sendSMS(sender, message, recipients) {
        try {
            // Convert array to comma-separated string if needed
            if (Array.isArray(recipients)) {
                recipients = recipients.join(',');
            }

            const response = await this.client.post('/sms', {
                sender,
                message,
                recipients
            });

            return response.data;

        } catch (error) {
            if (error.response) {
                // Server responded with error
                throw new Error(error.response.data.message || 'SMS sending failed');
            } else if (error.request) {
                // Request made but no response
                throw new Error('No response from server');
            } else {
                // Request setup error
                throw new Error(error.message);
            }
        }
    }

    async getBalance() {
        try {
            const response = await this.client.get('/balance');
            return response.data;
        } catch (error) {
            throw new Error('Failed to get balance: ' + error.message);
        }
    }

    async getDeliveryReport(messageId) {
        try {
            const response = await this.client.get(`/delivery/${messageId}`);
            return response.data;
        } catch (error) {
            throw new Error('Failed to get delivery report: ' + error.message);
        }
    }
}

// Usage Example
(async () => {
    const sms = new BulkSMSNigeria('YOUR_API_TOKEN');

    try {
        // Send single SMS
        const result = await sms.sendSMS(
            'YourBrand',
            'Hello from Node.js! This is a test message.',
            '2348012345678'
        );

        console.log('βœ“ Message sent successfully!');
        console.log(`  Message ID: ${result.data.message_id}`);
        console.log(`  Cost: ₦${result.data.total_cost}`);
        console.log(`  Balance: ₦${result.data.balance_after}`);

        // Send to multiple recipients
        const bulkResult = await sms.sendSMS(
            'YourBrand',
            'Bulk message to multiple recipients',
            ['2348012345678', '2348087654321', '2349012345678']
        );

        console.log(`\nβœ“ Bulk message sent to ${bulkResult.data.total_recipients} recipients`);

        // Check balance
        const balance = await sms.getBalance();
        console.log(`\nCurrent Balance: ₦${balance.data.balance}`);

    } catch (error) {
        console.error('βœ— Error:', error.message);
    }
})();

JavaScript (Browser) Integration

⚠️ Security Warning

Never use your API token in client-side JavaScript! It would be exposed to anyone viewing your page source. Always make API calls from your backend server. If you need SMS functionality in a web app, create a backend endpoint that securely calls the BulkSMS API.

Secure Pattern: Backend Proxy Endpoint

// Frontend (JavaScript)
async function sendOTP(phoneNumber) {
    try {
        const response = await fetch('/api/send-otp', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                // Use your app's authentication (session, JWT, etc.)
                'Authorization': `Bearer ${userAuthToken}`
            },
            body: JSON.stringify({ phone: phoneNumber })
        });

        const result = await response.json();

        if (result.success) {
            console.log('OTP sent successfully!');
        } else {
            console.error('Failed to send OTP:', result.message);
        }
    } catch (error) {
        console.error('Error:', error);
    }
}

// Backend (Node.js/Express) - This is where the API token is used
app.post('/api/send-otp', authenticateUser, async (req, res) => {
    const { phone } = req.body;

    // Verify user is authenticated
    if (!req.user) {
        return res.status(401).json({ success: false, message: 'Unauthorized' });
    }

    const otp = generateOTP(); // Generate 6-digit OTP

    try {
        // Call BulkSMS API from backend (secure)
        const sms = new BulkSMSNigeria(process.env.BULKSMS_API_TOKEN);
        await sms.sendSMS('YourApp', `Your OTP is: ${otp}`, phone);

        // Store OTP in session/database for verification
        req.session.otp = otp;

        res.json({ success: true, message: 'OTP sent' });
    } catch (error) {
        res.status(500).json({ success: false, message: 'Failed to send OTP' });
    }
});

Step 4: Advanced Features

Sending Bulk SMS

Send to multiple recipients in a single API call:

// Recipients as comma-separated string
{
  "sender": "YourBrand",
  "message": "Flash sale! 30% off all items today only.",
  "recipients": "2348012345678,2348087654321,2349012345678"
}

// Or as array (in JSON)
{
  "sender": "YourBrand",
  "message": "Flash sale! 30% off all items today only.",
  "recipients": ["2348012345678", "2348087654321", "2349012345678"]
}

Scheduled SMS

Schedule messages to be sent at a specific time:

{
  "sender": "YourBrand",
  "message": "Good morning! Your appointment is in 1 hour.",
  "recipients": "2348012345678",
  "schedule": "2025-12-05 08:00:00"  // YYYY-MM-DD HH:MM:SS format
}

Personalized Messages

Send personalized messages with merge fields:

// Python example
recipients_data = [
    {"phone": "2348012345678", "name": "John", "amount": "5000"},
    {"phone": "2348087654321", "name": "Sarah", "amount": "3200"},
]

for recipient in recipients_data:
    message = f"Hi {recipient['name']}, your order of ₦{recipient['amount']} has been confirmed!"
    sms.send_sms('ShopEase', message, recipient['phone'])

Getting Delivery Reports

// GET request to check delivery status
GET https://www.bulksmsnigeria.com/api/v2/delivery/{message_id}

// Response
{
  "status": "success",
  "data": {
    "message_id": "msg_abc123xyz789",
    "total_recipients": 3,
    "delivered": 2,
    "pending": 1,
    "failed": 0,
    "recipients": [
      {
        "phone": "2348012345678",
        "status": "delivered",
        "delivered_at": "2025-12-04 10:23:15"
      },
      {
        "phone": "2348087654321",
        "status": "delivered",
        "delivered_at": "2025-12-04 10:23:17"
      },
      {
        "phone": "2349012345678",
        "status": "pending",
        "reason": "Phone off"
      }
    ]
  }
}

Checking Account Balance

// GET request
GET https://www.bulksmsnigeria.com/api/v2/balance

// Response
{
  "status": "success",
  "data": {
    "balance": 1250.50,
    "currency": "NGN"
  }
}

Step 5: Error Handling

Common HTTP Status Codes

Status Code Meaning Action
200 Success Request processed successfully
400 Bad Request Check request format, missing/invalid parameters
401 Unauthorized Invalid or missing API token
403 Forbidden Sender ID not registered or insufficient credits
429 Too Many Requests Rate limit exceeded, wait and retry
500 Server Error Retry with exponential backoff

Error Response Format

{
  "status": "error",
  "message": "Insufficient credits. You need ₦60 but have ₦25.",
  "error_code": "INSUFFICIENT_CREDITS",
  "data": {
    "required": 60.00,
    "available": 25.00,
    "top_up_url": "https://www.bulksmsnigeria.com/wallet/fund"
  }
}

Robust Error Handling Example (Python)

import requests
import time

def send_sms_with_retry(sms_client, sender, message, recipients, max_retries=3):
    """
    Send SMS with automatic retry on transient failures
    """
    for attempt in range(max_retries):
        try:
            result = sms_client.send_sms(sender, message, recipients)
            return result

        except requests.exceptions.HTTPError as e:
            status_code = e.response.status_code
            error_data = e.response.json()

            if status_code == 400:
                # Bad request - don't retry, fix the request
                raise Exception(f"Invalid request: {error_data['message']}")

            elif status_code == 401:
                # Unauthorized - API token invalid
                raise Exception("Authentication failed. Check your API token.")

            elif status_code == 403:
                # Forbidden - likely insufficient credits or unregistered sender ID
                raise Exception(f"Access denied: {error_data['message']}")

            elif status_code == 429:
                # Rate limit - wait and retry
                wait_time = 2 ** attempt  # Exponential backoff: 1s, 2s, 4s
                print(f"Rate limited. Waiting {wait_time}s before retry...")
                time.sleep(wait_time)
                continue

            elif status_code >= 500:
                # Server error - retry with backoff
                if attempt < max_retries - 1:
                    wait_time = 2 ** attempt
                    print(f"Server error. Retrying in {wait_time}s...")
                    time.sleep(wait_time)
                    continue
                else:
                    raise Exception("Server error persists after retries")

            else:
                raise Exception(f"Unexpected error: {error_data['message']}")

        except requests.exceptions.Timeout:
            if attempt < max_retries - 1:
                print(f"Request timeout. Retrying...")
                time.sleep(2)
                continue
            else:
                raise Exception("Request timed out after multiple retries")

        except requests.exceptions.ConnectionError:
            if attempt < max_retries - 1:
                print(f"Connection error. Retrying...")
                time.sleep(2)
                continue
            else:
                raise Exception("Could not connect to API server")

    raise Exception("Failed after maximum retries")

# Usage
try:
    result = send_sms_with_retry(sms, 'YourBrand', 'Test message', '2348012345678')
    print("βœ“ SMS sent successfully!")
except Exception as e:
    print(f"βœ— Failed to send SMS: {e}")
    # Log error, send alert, etc.

Step 6: Best Practices

1. Secure API Token Storage

βœ“ DO:

  • β€’ Store API tokens in environment variables (process.env.BULKSMS_API_TOKEN)
  • β€’ Use configuration files outside web root (.env files)
  • β€’ Rotate tokens periodically (every 6-12 months)
  • β€’ Use different tokens for development and production
  • β€’ Implement token encryption in database if storing there

βœ— DON'T:

  • β€’ Hardcode tokens in source code
  • β€’ Commit tokens to version control (Git)
  • β€’ Expose tokens in client-side JavaScript
  • β€’ Share tokens via email or insecure channels
  • β€’ Use production tokens for testing

2. Validate Phone Numbers

// PHP phone number validation
function validateNigerianPhone($phone) {
    // Remove spaces, dashes, parentheses
    $phone = preg_replace('/[^0-9]/', '', $phone);

    // Check format: 234XXXXXXXXXX (13 digits starting with 234)
    // or 0XXXXXXXXXX (11 digits starting with 0)
    if (preg_match('/^234[789][01]\d{8}$/', $phone)) {
        return $phone; // Already in international format
    } elseif (preg_match('/^0[789][01]\d{8}$/', $phone)) {
        return '234' . substr($phone, 1); // Convert to international
    }

    return false; // Invalid format
}

// Usage
$phone = validateNigerianPhone('08012345678');
if ($phone) {
    // Send SMS to $phone (234801234567)
} else {
    // Show error: invalid phone number
}

3. Implement Rate Limiting

Respect the API rate limit of 100 requests per minute:

// Python rate limiting example
import time
from collections import deque

class RateLimiter:
    def __init__(self, max_calls=100, time_window=60):
        self.max_calls = max_calls
        self.time_window = time_window
        self.calls = deque()

    def wait_if_needed(self):
        now = time.time()

        # Remove old calls outside time window
        while self.calls and self.calls[0] < now - self.time_window:
            self.calls.popleft()

        # If at limit, wait until oldest call expires
        if len(self.calls) >= self.max_calls:
            sleep_time = self.calls[0] + self.time_window - now
            time.sleep(sleep_time)
            self.calls.popleft()

        # Record this call
        self.calls.append(now)

# Usage
limiter = RateLimiter(max_calls=100, time_window=60)

for phone in large_recipient_list:
    limiter.wait_if_needed()
    sms.send_sms('YourBrand', 'Message', phone)

4. Queue SMS for Background Processing

For large campaigns, use job queues instead of sending synchronously:

// Node.js with Bull Queue
const Queue = require('bull');
const smsQueue = new Queue('sms-sending');

// Producer: Add SMS jobs to queue
async function queueBulkSMS(recipients, message) {
    for (const phone of recipients) {
        await smsQueue.add({
            sender: 'YourBrand',
            message: message,
            recipient: phone
        });
    }
}

// Consumer: Process SMS jobs
smsQueue.process(async (job) => {
    const { sender, message, recipient } = job.data;
    const sms = new BulkSMSNigeria(process.env.BULKSMS_API_TOKEN);

    try {
        await sms.sendSMS(sender, message, recipient);
        return { success: true };
    } catch (error) {
        // Will retry automatically based on queue settings
        throw error;
    }
});

5. Log All API Interactions

// Python logging example
import logging

logging.basicConfig(
    filename='sms_api.log',
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

def send_sms_with_logging(sms_client, sender, message, recipients):
    logging.info(f"Sending SMS to {len(recipients.split(','))} recipients")

    try:
        result = sms_client.send_sms(sender, message, recipients)
        logging.info(f"SMS sent successfully. Message ID: {result['data']['message_id']}")
        logging.info(f"Cost: ₦{result['data']['total_cost']}, Balance: ₦{result['data']['balance_after']}")
        return result

    except Exception as e:
        logging.error(f"SMS sending failed: {str(e)}")
        raise

6. Monitor Account Balance

Check balance before sending to avoid failures:

// Check balance before campaign
const balance = await sms.getBalance();
const estimatedCost = recipientCount * 6; // Assume ₦6 per SMS

if (balance.data.balance < estimatedCost) {
    throw new Error(
        `Insufficient balance. Need ₦${estimatedCost} but have ₦${balance.data.balance}`
    );
}

// Proceed with sending
await sms.sendSMS('YourBrand', message, recipients);

Complete Integration Checklist

Before Going Live:

Common Integration Issues & Solutions

Issue 1: SSL Certificate Verification Errors

Error:

SSL: CERTIFICATE_VERIFY_FAILED

Solution:

Update your system's CA certificates or ensure your HTTP library is using updated certificates. Never disable SSL verification in production!

Issue 2: Timeout Errors on Large Campaigns

Solution:

  • β€’ Break large recipient lists into batches (100-500 per request)
  • β€’ Use background jobs/queues for bulk sending
  • β€’ Increase timeout setting to 30-60 seconds
  • β€’ Implement retry logic with exponential backoff

Issue 3: Messages Showing Random Numbers Instead of Sender ID

Causes:

  • β€’ Sender ID not registered/approved
  • β€’ Using unregistered sender ID in API call
  • β€’ Network operator rejection

Solution:

Register your sender ID through your dashboard and wait for approval (3-7 days) before using in campaigns.

Next Steps

Congratulations! You now have a fully functional SMS API integration. Here's what to do next:

  1. 1. Test thoroughly: Send test messages to all Nigerian networks (MTN, Glo, Airtel, 9mobile)
  2. 2. Implement monitoring: Set up alerts for API errors, low balance, and delivery failures
  3. 3. Optimize costs: Review message lengths, avoid Unicode triggers, clean contact lists
  4. 4. Scale gradually: Start with small campaigns, monitor performance, then scale up
  5. 5. Read full documentation: Explore advanced features like webhooks, templates, and analytics

Ready to Integrate SMS Into Your App?

Get your API credentials, 50 free SMS credits, and start sending in minutes. Complete documentation, code examples, and 24/7 developer support included.

Ready to Put This Into Practice?

Start sending bulk SMS to your customers today with 50 free SMS credits.

Get Started Free