Integrate with Ease
Our platform provides a robust JSON API for resellers to manage sub-accounts, credits, and transactional emails. This documentation is designed to guide you through the integration process, from your first authentication to high-volume email delivery.
Core Concepts
Before diving in, it's helpful to understand the two main ways to interact with our platform:
- JSON API: Best for dynamic management (creating users, checking balances) and sending specific transactional emails.
- SMTP Relay: Ideal for legacy applications or mail servers that already support the SMTP protocol.
Welcome to the MSpace Bulk Email Developer Hub. Our platform offers a high-performance, enterprise-grade SMTP and JSON API infrastructure for resellers and application developers. Scale your outreach with precision using our robust integration options.
https://bulkemail.mspace.co.ke/email
Use this base URL for all API requests. All endpoints require HTTPS for security.
Authentication
Secure your requests using one of the two supported authentication methods, depending on the endpoint you are accessing. Security is our top priority; never share your credentials or API keys in public repositories.
Basic Auth
Usage: Reseller API Management.
Combine your username and password with a colon, then encode the string
in Base64.
Authorization: Basic b64(user:pass)
API Key
Usage: Transactional Messaging.
Generate keys in your dashboard. Pass the key directly in the JSON body
of your request.
"apiKey": "YOUR_SECURE_KEY"
Reseller: Create Sub-User
Programmatically provision new sub-accounts. Perfect for integrating our email services into your own SaaS dashboard or customer portal.
/api/reseller/createSubUser
Request Payload Details
| Field | Type | Required | Description |
|---|---|---|---|
username |
String | Yes | The unique login name for the new client. |
password |
String | Yes | Must be at least 8 characters long. |
credits |
Integer | No | Initial credit allocation (defaults to 0). |
mobile |
String | No | Contact phone (MSISDN format, e.g., 254...). |
Example Implementation
curl -X POST "https://bulkemail.mspace.co.ke/email/api/reseller/createSubUser" \
-u "YOUR_USERNAME:YOUR_PASSWORD" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"username": "developer",
"password": "developer123",
"firstname": "Dev",
"surname": "Loper",
"organization": "Winsy",
"mobile": "254729651022",
"credits": 50
}'
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.util.Base64;
public class CreateSubUser {
public static void main(String[] args) throws Exception {
String auth = "YOUR_USERNAME:YOUR_PASSWORD";
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
String json = """
{
"username": "developer",
"password": "developer123",
"firstname": "Dev",
"surname": "Loper",
"organization": "Winsy",
"mobile": "254729651022",
"credits": 50
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://bulkemail.mspace.co.ke/email/api/reseller/createSubUser"))
.header("Authorization", "Basic " + encodedAuth)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
<?php
$url = "https://bulkemail.mspace.co.ke/email/api/reseller/createSubUser";
$username = "YOUR_USERNAME";
$password = "YOUR_PASSWORD";
$data = [
"username" => "developer",
"password" => "developer123",
"firstname" => "Dev",
"surname" => "Loper",
"organization" => "Winsy",
"mobile" => "254729651022",
"credits" => 50
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import urllib.request
import json
import base64
url = "https://bulkemail.mspace.co.ke/email/api/reseller/createSubUser"
auth = base64.b64encode(b"YOUR_USERNAME:YOUR_PASSWORD").decode("ascii")
data = {
"username": "developer",
"password": "developer123",
"firstname": "Dev",
"surname": "Loper",
"organization": "Winsy",
"mobile": "254729651022",
"credits": 50
}
req = urllib.request.Request(url, data=json.dumps(data).encode("utf-8"), method="POST")
req.add_header("Authorization", f"Basic {auth}")
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req) as response:
print(response.read().decode("utf-8"))
const https = require('https');
const data = JSON.stringify({
username: 'developer',
password: 'developer123',
firstname: 'Dev',
surname: 'Loper',
organization: 'Winsy',
mobile: '254729651022',
credits: 50
});
const options = {
hostname: 'bulkemail.mspace.co.ke',
path: '/email/api/reseller/createSubUser',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length,
'Authorization': 'Basic ' + Buffer.from('YOUR_USERNAME:YOUR_PASSWORD').toString('base64')
}
};
const req = https.request(options, res => {
res.on('data', d => process.stdout.write(d));
});
req.on('error', error => console.error(error));
req.write(data);
req.end();
package main
import (
"bytes"
"encoding/base64"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://bulkemail.mspace.co.ke/email/api/reseller/createSubUser"
auth := base64.StdEncoding.EncodeToString([]byte("YOUR_USERNAME:YOUR_PASSWORD"))
jsonStr := []byte(`{
"username": "developer",
"password": "developer123",
"firstname": "Dev",
"surname": "Loper",
"organization": "Winsy",
"mobile": "254729651022",
"credits": 50
}`)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
req.Header.Set("Authorization", "Basic "+auth)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program {
static async Task Main() {
var url = "https://bulkemail.mspace.co.ke/email/api/reseller/createSubUser";
var auth = Convert.ToBase64String(Encoding.ASCII.GetBytes("YOUR_USERNAME:YOUR_PASSWORD"));
var json = @"{
""username"": ""developer"",
""password"": ""developer123"",
""firstname"": ""Dev"",
""surname"": ""Loper"",
""organization"": ""Winsy"",
""mobile"": ""254729651022"",
""credits"": 50
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Basic " + auth);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
}
}
Sample Responses
{
"status": "success",
"message": "Sub-user created successfully"
}
{
"status": "error",
"message": "Authentication passed failed."
}
Reseller: Manage Credits
Transfer email credits between your master account and sub-accounts in real-time.
/api/reseller/manageCredits
ADD action.
Action Types
"ADD": Transfer credits from your balance to the sub-user."DEDUCT": Reclaim credits from sub-user to your balance.
Example Implementation
curl -X POST "https://bulkemail.mspace.co.ke/email/api/reseller/manageCredits" \
-u "YOUR_USERNAME:YOUR_PASSWORD" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"sub_username": "developer",
"action": "ADD",
"amount": 100
}'
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.util.Base64;
public class ManageCredits {
public static void main(String[] args) throws Exception {
String auth = "YOUR_USERNAME:YOUR_PASSWORD";
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
String json = """
{
"sub_username": "developer",
"action": "ADD",
"amount": 100
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://bulkemail.mspace.co.ke/email/api/reseller/manageCredits"))
.header("Authorization", "Basic " + encodedAuth)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
<?php
$username = "YOUR_USERNAME";
$password = "YOUR_PASSWORD";
$data = [
"sub_username" => "developer",
"action" => "ADD",
"amount" => 100
];
$ch = curl_init("https://bulkemail.mspace.co.ke/email/api/reseller/manageCredits");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import urllib.request
import json
import base64
url = "https://bulkemail.mspace.co.ke/email/api/reseller/manageCredits"
auth = base64.b64encode(b"YOUR_USERNAME:YOUR_PASSWORD").decode("ascii")
data = {
"sub_username": "developer",
"action": "ADD",
"amount": 100
}
req = urllib.request.Request(url, data=json.dumps(data).encode("utf-8"), method="POST")
req.add_header("Authorization", f"Basic {auth}")
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req) as response:
print(response.read().decode("utf-8"))
const https = require('https');
const data = JSON.stringify({
sub_username: 'developer',
action: 'ADD',
amount: 100
});
const options = {
hostname: 'bulkemail.mspace.co.ke',
path: '/email/api/reseller/manageCredits',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length,
'Authorization': 'Basic ' + Buffer.from('YOUR_USERNAME:YOUR_PASSWORD').toString('base64')
}
};
const req = https.request(options, res => {
res.on('data', d => process.stdout.write(d));
});
req.on('error', error => console.error(error));
req.write(data);
req.end();
package main
import (
"bytes"
"encoding/base64"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://bulkemail.mspace.co.ke/email/api/reseller/manageCredits"
auth := base64.StdEncoding.EncodeToString([]byte("YOUR_USERNAME:YOUR_PASSWORD"))
jsonStr := []byte(`{
"sub_username": "developer",
"action": "ADD",
"amount": 100
}`)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
req.Header.Set("Authorization", "Basic "+auth)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program {
static async Task Main() {
var url = "https://bulkemail.mspace.co.ke/email/api/reseller/manageCredits";
var auth = Convert.ToBase64String(Encoding.ASCII.GetBytes("YOUR_USERNAME:YOUR_PASSWORD"));
var json = @"{
""sub_username"": ""developer"",
""action"": ""ADD"",
""amount"": 100
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Basic " + auth);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
}
}
Sample Responses
{
"status": "success",
"message": "Credits updated",
"reseller_balance": 1015,
"subuser_balance": 20
}
{
"status": "error",
"message": "Insufficient reseller credits"
}
{
"status": "error",
"message": "Authentication passed failed."
}
Messaging: Send Transactional
Send high-priority individual emails with attachment and HTML support. Transactional emails are typically automated responses to user actions, such as welcome emails, password resets, or order confirmations.
/api/send
Parameters Reference
| Field | Required | Description |
|---|---|---|
apiKey |
Yes | Generate this in the API Keys tab of your dashboard. |
to |
Yes | Recipient email address. |
subject |
Yes | Email subject line. |
body |
Yes | HTML or Plain Text content. |
fromName |
No | Custom sender name show to recipient. |
Example Implementation
curl -X POST "https://bulkemail.mspace.co.ke/email/api/send" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"apiKey": "YOUR_API_KEY",
"to": "recipient@example.com",
"subject": "Hello from MSpace",
"body": "<h1>HTML Content</h1>",
"fromName": "MSpace System"
}'
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class SendTransactional {
public static void main(String[] args) throws Exception {
String json = """
{
"apiKey": "YOUR_API_KEY",
"to": "recipient@example.com",
"subject": "Hello from MSpace",
"body": "<h1>HTML Content</h1>",
"fromName": "MSpace System"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://bulkemail.mspace.co.ke/email/api/send"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
<?php
$data = [
"apiKey" => "YOUR_API_KEY",
"to" => "recipient@example.com",
"subject" => "Hello from MSpace",
"body" => "<h1>HTML Content</h1>",
"fromName" => "MSpace System"
];
$ch = curl_init("https://bulkemail.mspace.co.ke/email/api/send");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
import urllib.request
import json
url = "https://bulkemail.mspace.co.ke/email/api/send"
data = {
"apiKey": "YOUR_API_KEY",
"to": "recipient@example.com",
"subject": "Hello from MSpace",
"body": "<h1>HTML Content</h1>",
"fromName": "MSpace System"
}
req = urllib.request.Request(url, data=json.dumps(data).encode("utf-8"), method="POST")
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req) as response:
print(response.read().decode("utf-8"))
const https = require('https');
const data = JSON.stringify({
apiKey: 'YOUR_API_KEY',
to: 'recipient@example.com',
subject: 'Hello from MSpace',
body: '<h1>HTML Content</h1>',
fromName: 'MSpace System'
});
const options = {
hostname: 'bulkemail.mspace.co.ke/email'
port: 2525,
path: '/email/api/send',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
};
const req = https.request(options, res => {
res.on('data', d => process.stdout.write(d));
});
req.on('error', error => console.error(error));
req.write(data);
req.end();
package main
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://bulkemail.mspace.co.ke/email/api/send"
jsonStr := []byte(`{
"apiKey": "YOUR_API_KEY",
"to": "recipient@example.com",
"subject": "Hello from MSpace",
"body": "<h1>HTML Content</h1>",
"fromName": "MSpace System"
}`)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program {
static async Task Main() {
var url = "https://bulkemail.mspace.co.ke/email/api/send";
var json = @"{
""apiKey"": ""YOUR_API_KEY"",
""to"": ""recipient@example.com"",
""subject"": ""Hello from MSpace"",
""body"": ""<h1>HTML Content</h1>"",
""fromName"": ""MSpace System""
}";
using var client = new HttpClient();
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
}
}
Sample Responses
{
"status": "success",
"message": "Email queued successfully",
"messageId": "msg_123456789"
}
{
"status": "error",
"message": "Authentication passed failed."
}
Messaging: SMTP Integration
Integrate with our relay servers using standard SMTP protocols. Perfect for traditional mail servers (like Postfix or Exchange) and legacy applications that already have SMTP support built-in.
API vs SMTP: Which one to choose?
Use the JSON API if you need programmatic control and better error handling within your code. Use SMTP if you want a drop-in solution for existing software that doesn't require new code development.
Code Implementation Examples
Choose your preferred technology stack to view a production-ready implementation example.
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
public class EmailSender {
public static void main(String[] args) {
final String username = "YOUR_USERNAME";
final String password = "YOUR_PASSWORD";
Properties prop = new Properties();
prop.put("mail.smtp.host", "bulkemail.mspace.co.ke");
prop.put("mail.smtp.port", "2525");
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.starttls.enable", "true");
Session session = Session.getInstance(prop, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("noreply@mspace.co.ke"));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse("recipient@example.com"));
message.setSubject("Hello from MSpace");
message.setText("This is the email body.");
Transport.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
<?php
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'bulkemail.mspace.co.ke';
$mail->SMTPAuth = true;
$mail->Username = 'YOUR_USERNAME';
$mail->Password = 'YOUR_PASSWORD';
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 2525;
$mail->setFrom('info@mspace.co.ke', 'MSpace Info');
$mail->addAddress($recipient);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->send();
import smtplib
from email.mime.text import MIMEText
def send_email(recipient, body, subject):
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = "Sender Name <noreply@mspace.co.ke>"
msg['To'] = recipient
with smtplib.SMTP("bulkemail.mspace.co.ke", 2525) as server:
server.starttls()
server.login("YOUR_USERNAME", "YOUR_PASSWORD")
server.send_message(msg)
const nodemailer = require('nodemailer');
async function sendMail() {
let transporter = nodemailer.createTransport({
host: 'bulkemail.mspace.co.ke',
port: 2525,
secure: false,
auth: {
user: 'YOUR_USERNAME',
pass: 'YOUR_PASSWORD'
}
});
let info = await transporter.sendMail({
from: '"Sender Name" <noreply@mspace.co.ke>',
to: 'recipient@example.com',
subject: 'Hello from MSpace',
text: 'Hello world?',
html: '<b>Hello world?</b>'
});
}
package main
import (
"net/smtp"
)
func main() {
auth := smtp.PlainAuth("", "YOUR_USERNAME", "YOUR_PASSWORD", "bulkemail.mspace.co.ke")
to := []string{"recipient@example.com"}
msg := []byte("To: recipient@example.com\r\n" +
"Subject: Hello from MSpace\r\n" +
"\r\n" +
"This is the email body.\r\n")
err := smtp.SendMail("bulkemail.mspace.co.ke:2525", auth, "noreply@mspace.co.ke", to, msg)
if err != nil {
panic(err)
}
}
using System.Net;
using System.Net.Mail;
public class EmailSender {
public void Send() {
var client = new SmtpClient("bulkemail.mspace.co.ke", 2525) {
Credentials = new NetworkCredential("YOUR_USERNAME", "YOUR_PASSWORD"),
EnableSsl = true
};
client.Send("noreply@mspace.co.ke", "recipient@example.com", "Subject", "Body");
}
}
Error Response Reference
When an error occurs, the API returns a corresponding error code and descriptive message. Understanding these responses helps you build more resilient integrations.
| Status | Message | Context / Troubleshooting |
|---|---|---|
error |
Authentication passed failed. | Verify that your Basic Auth header is correctly Base64 encoded and matching your dashboard login. |
error |
Insufficient reseller credits | Your master account balance (reseller balance) is too low. Top up via the portal. |
error |
The target sub-username was not found. | The sub_username provided does not exist under your
reseller account. |
error |
Rate limit or connection error. | You've exceeded the allowed requests per second. Implement a retry mechanism with exponential backoff. |
Integration Best Practices
Security
- Always use HTTPS.
- Rotate API keys every 90 days.
- Whitelist your server IPs in the dashboard if available.
Performance
- Batch requests when manageable.
- Avoid frequent polling; use our dashboard for status where possible.
- Keep payloads concise for faster processing.