Email API Guide
Send rich email messages through the Communications API. Perfect for detailed notifications, newsletters, and HTML-formatted communications.
Endpoint
POST /api/SendMessage_V3/Email
Host: m5api.groupcall.com
Content-Type: application/json
Basic Email Request
{
"messageData": [
{
"CustomerId": "your-customer-id",
"Password": "your-api-key",
"Recipients": [
{
"EmailAddress": "[email protected]"
}
],
"EmailSubject": "Important School Update",
"EmailBody": "<h1>Welcome!</h1><p>This is an <strong>HTML email</strong> with rich formatting.</p>",
"CallbackUrl": "https://your-app.com/email-callback"
}
]
}
Request Fields
Required Fields
Field | Type | Description | Example |
---|---|---|---|
CustomerId | String | Your customer account ID | "1469" |
Password | String | Customer API key | "your-api-key" |
Recipients | Array | List of email recipient objects (see Recipients Reference) | [{"EmailAddress": "[email protected]"}] |
EmailSubject | String | Email subject line | "Important Update" |
EmailBody | String | Email content (HTML or plain text) | "<p>Hello!</p>" |
Optional Fields
Field | Type | Description | Example |
---|---|---|---|
ClientRef | String | Your reference for tracking | "EMAIL-001" |
CallbackUrl | String | URL for delivery status updates | "https://app.com/callback" |
EmailSentFromName | String | Sender display name | "School Office" |
EmailSentFromAddress | String | Sender email address | "[email protected]" |
EmailReplyToAddress | String | Reply-to email address | "[email protected]" |
Attachments | Array | List of file attachments | [{"FileName": "report.pdf", "FileData": "base64data..."}] |
Examples
Basic HTML Email
{
"messageData": [
{
"CustomerId": "1469",
"Password": "your-api-key",
"Recipients": [
{
"EmailAddress": "[email protected]"
}
],
"EmailSubject": "Weekly Newsletter",
"EmailBody": "<!DOCTYPE html><html><body><h1>This Week at School</h1><p>Here are the important updates for this week...</p></body></html>",
"EmailSentFromName": "School Communications",
"EmailSentFromAddress": "[email protected]",
"ClientRef": "NEWSLETTER-2025-03"
}
]
}
Multiple Recipients
{
"messageData": [
{
"CustomerId": "1469",
"Password": "your-api-key",
"Recipients": [
{
"EmailAddress": "[email protected]"
},
{
"EmailAddress": "[email protected]"
},
{
"EmailAddress": "[email protected]"
}
],
"EmailSubject": "Emergency School Closure",
"EmailBody": "<h1>School Closure Notice</h1><p>Due to severe weather conditions, school will be closed tomorrow, July 16th, 2025.</p><p>Please stay safe and we'll see you when conditions improve.</p>",
"EmailSentFromName": "School Administration",
"CallbackUrl": "https://school-system.com/email-callback"
}
]
}
Plain Text Email
{
"messageData": [
{
"CustomerId": "1469",
"Password": "your-api-key",
"Recipients": [
{
"EmailAddress": "[email protected]"
}
],
"EmailSubject": "Simple Text Message",
"EmailBody": "This is a plain text email message.\n\nIt supports line breaks and basic formatting.",
"ClientRef": "TEXT-EMAIL-001"
}
]
}
Email with Attachments
{
"messageData": [
{
"CustomerId": "1469",
"Password": "your-api-key",
"Recipients": [
{
"EmailAddress": "[email protected]"
}
],
"EmailSubject": "Monthly Report - July 2025",
"EmailBody": "<h1>Monthly Report</h1><p>Please find attached your child's monthly progress report.</p><p>If you have any questions, please don't hesitate to contact us.</p>",
"EmailSentFromName": "School Administration",
"EmailSentFromAddress": "[email protected]",
"Attachments": [
{
"FileName": "monthly_report_july.pdf",
"FileData": "JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovUGFnZXMgMiAwIFIKPj4KZW5kb2JqCjQgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL1BhcmVudCAyIDAgUgovUmVzb3VyY2VzIDw8Ci9Gb250IDw8Ci9GMSAzIDAgUgo+PgpzdHJlYW0K..."
},
{
"FileName": "attendance_summary.xlsx",
"FileData": "UEsDBBQABgAIAAAAIQC2gziS/gAAAOEBAAATAAAAW0NvbnRlbnRfVHlwZXNdLnhtbJSRQU7DMBBF70jcwfLWJU67QAgl7QIWlNCilCv0fp2z4X5ndmww3z8PvMB2fF..."
}
],
"ClientRef": "REPORT-JULY-2025"
}
]
}
Response Format
Success Response
[
{
"WarningMessages": [],
"errorMsg": "OK 1 messages queued for sending",
"MessageSentId": 0,
"MessageId": "1469.20250715.email-unique-id-abc123",
"statusMsg": "In Queue",
"transmitDateTime": "2025-07-15T17:28:54.5859378Z",
"ClientRef": "EMAIL-001"
}
]
Error Response
[
{
"WarningMessages": ["Invalid email address: invalid-email"],
"errorMsg": "No recipients with valid addresses",
"MessageSentId": 0,
"MessageId": null,
"statusMsg": null,
"transmitDateTime": null,
"ClientRef": "EMAIL-001"
}
]
Implementation Examples
Node.js/JavaScript
const API_BASE = 'https://m5api.groupcall.com';
async function sendEmail(customerId, apiKey, emailData) {
const payload = {
messageData: [{
CustomerId: customerId,
Password: apiKey,
Recipients: emailData.recipients.map(email => ({
EmailAddress: email
})),
EmailSubject: emailData.subject,
EmailBody: emailData.body,
EmailSentFromName: emailData.fromName,
EmailSentFromAddress: emailData.fromAddress,
ClientRef: emailData.clientRef,
CallbackUrl: emailData.callbackUrl
}]
};
try {
const response = await fetch(`${API_BASE}/api/SendMessage_V3/Email`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
const result = await response.json();
if (Array.isArray(result) && result[0]) {
const messageResult = result[0];
if (messageResult.errorMsg && messageResult.errorMsg.startsWith('OK') && messageResult.MessageId) {
return {
success: true,
messageId: messageResult.MessageId,
status: messageResult.statusMsg,
timestamp: messageResult.transmitDateTime
};
} else {
const errorMsg = messageResult.errorMsg ||
(messageResult.WarningMessages && messageResult.WarningMessages[0]) ||
'Unknown error';
throw new Error(errorMsg);
}
}
throw new Error('Invalid response format');
} catch (error) {
throw new Error(`Email sending failed: ${error.message}`);
}
}
// Usage
await sendEmail('1469', 'your-api-key', {
recipients: ['[email protected]', '[email protected]'],
subject: 'Important School Update',
body: '<h1>Update</h1><p>School will start 1 hour late tomorrow due to weather.</p>',
fromName: 'School Office',
fromAddress: '[email protected]',
clientRef: 'UPDATE-001',
callbackUrl: 'https://your-app.com/email-callback'
});
Complete JavaScript Example with Attachments
const fs = require('fs');
// Helper function to encode files
function encodeFileToBase64(filePath) {
const fileBuffer = fs.readFileSync(filePath);
return fileBuffer.toString('base64');
}
// Enhanced sendEmail function with attachment support
async function sendEmailWithAttachments(customerId, apiKey, emailData) {
const payload = {
messageData: [{
CustomerId: customerId,
Password: apiKey,
Recipients: emailData.recipients.map(recipient =>
typeof recipient === 'string' ? { EmailAddress: recipient } : recipient
),
EmailSubject: emailData.subject,
EmailBody: emailData.body,
EmailSentFromName: emailData.fromName,
EmailSentFromAddress: emailData.fromAddress,
ClientRef: emailData.clientRef,
CallbackUrl: emailData.callbackUrl,
...(emailData.attachments && { Attachments: emailData.attachments })
}]
};
try {
const response = await fetch(`${API_BASE}/api/SendMessage_V3/Email`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
const result = await response.json();
if (Array.isArray(result) && result[0]) {
const messageResult = result[0];
if (messageResult.errorMsg && messageResult.errorMsg.startsWith('OK') && messageResult.MessageId) {
return {
success: true,
messageId: messageResult.MessageId,
status: messageResult.statusMsg,
timestamp: messageResult.transmitDateTime
};
} else {
const errorMsg = messageResult.errorMsg ||
(messageResult.WarningMessages && messageResult.WarningMessages[0]) ||
'Unknown error';
throw new Error(errorMsg);
}
}
throw new Error('Invalid response format');
} catch (error) {
throw new Error(`Email sending failed: ${error.message}`);
}
}
// Usage with attachments
await sendEmailWithAttachments('1469', 'your-api-key', {
recipients: [
{ EmailAddress: '[email protected]' },
{ EmailAddress: '[email protected]' }
],
subject: 'Monthly Report with Attachments',
body: '<h1>Monthly Report</h1><p>Please find the attached documents.</p>',
fromName: 'School Office',
fromAddress: '[email protected]',
clientRef: 'MONTHLY-REPORT-001',
callbackUrl: 'https://your-app.com/email-callback',
attachments: [
{
FileName: 'monthly_report.pdf',
FileData: encodeFileToBase64('./reports/monthly_report.pdf')
},
{
FileName: 'attendance_summary.xlsx',
FileData: encodeFileToBase64('./reports/attendance_summary.xlsx')
}
]
});
Python
import requests
from typing import List, Dict, Any
API_BASE = 'https://m5api.groupcall.com'
def send_email(customer_id: str, api_key: str, email_data: Dict[str, Any]) -> Dict[str, Any]:
payload = {
'messageData': [{
'CustomerId': customer_id,
'Password': api_key,
'Recipients': [
{'EmailAddress': email}
for email in email_data['recipients']
],
'EmailSubject': email_data['subject'],
'EmailBody': email_data['body'],
'EmailSentFromName': email_data.get('from_name'),
'EmailSentFromAddress': email_data.get('from_address'),
'ClientRef': email_data.get('client_ref'),
'CallbackUrl': email_data.get('callback_url')
}]
}
try:
response = requests.post(
f'{API_BASE}/api/SendMessage_V3/Email',
headers={'Content-Type': 'application/json'},
json=payload,
timeout=30
)
response.raise_for_status()
result = response.json()
if result and isinstance(result, list) and result[0]:
message_result = result[0]
if (message_result.get('errorMsg', '').startswith('OK') and
message_result.get('MessageId')):
return {
'success': True,
'message_id': message_result['MessageId'],
'status': message_result.get('statusMsg'),
'timestamp': message_result.get('transmitDateTime')
}
else:
error_msg = (message_result.get('errorMsg') or
(message_result.get('WarningMessages', [None])[0]) or
'Unknown error')
raise Exception(error_msg)
raise Exception('Invalid response format')
except requests.RequestException as e:
raise Exception(f'Email sending failed: {str(e)}')
# Usage
result = send_email('1469', 'your-api-key', {
'recipients': [
{'EmailAddress': '[email protected]'},
{'EmailAddress': '[email protected]'}
],
'subject': 'Important School Update',
'body': '<h1>Update</h1><p>School will start 1 hour late tomorrow due to weather.</p>',
'from_name': 'School Office',
'from_address': '[email protected]',
'client_ref': 'UPDATE-001',
'callback_url': 'https://your-app.com/email-callback'
})
C#
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public class EmailApiClient
{
private readonly HttpClient _httpClient;
private const string API_BASE = "https://m5api.groupcall.com";
public EmailApiClient()
{
_httpClient = new HttpClient();
}
public async Task<EmailResult> SendEmailAsync(string customerId, string apiKey, EmailData emailData)
{
var payload = new
{
messageData = new[]
{
new
{
CustomerId = customerId,
Password = apiKey,
Recipients = emailData.Recipients.Select(email => new { EmailAddress = email }),
EmailSubject = emailData.Subject,
EmailBody = emailData.Body,
EmailSentFromName = emailData.FromName,
EmailSentFromAddress = emailData.FromAddress,
ClientRef = emailData.ClientRef,
CallbackUrl = emailData.CallbackUrl
}
}
};
var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");
try
{
var response = await _httpClient.PostAsync($"{API_BASE}/api/SendMessage_V3/Email", content);
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync();
var results = JsonSerializer.Deserialize<EmailApiResponse[]>(responseJson);
if (results != null && results.Length > 0)
{
var result = results[0];
if (!string.IsNullOrEmpty(result.ErrorMsg) &&
result.ErrorMsg.StartsWith("OK") &&
!string.IsNullOrEmpty(result.MessageId))
{
return new EmailResult
{
Success = true,
MessageId = result.MessageId,
Status = result.StatusMsg,
Timestamp = result.TransmitDateTime
};
}
else
{
var errorMsg = result.ErrorMsg ??
result.WarningMessages?.FirstOrDefault() ??
"Unknown error";
throw new Exception(errorMsg);
}
}
throw new Exception("Invalid response format");
}
catch (Exception ex)
{
throw new Exception($"Email sending failed: {ex.Message}", ex);
}
}
}
public class EmailData
{
public List<string> Recipients { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public string FromName { get; set; }
public string FromAddress { get; set; }
public string ClientRef { get; set; }
public string CallbackUrl { get; set; }
}
public class EmailResult
{
public bool Success { get; set; }
public string MessageId { get; set; }
public string Status { get; set; }
public DateTime? Timestamp { get; set; }
}
public class EmailApiResponse
{
public string[] WarningMessages { get; set; }
public string ErrorMsg { get; set; }
public int MessageSentId { get; set; }
public string MessageId { get; set; }
public string StatusMsg { get; set; }
public DateTime? TransmitDateTime { get; set; }
}
// Usage
var client = new EmailApiClient();
var result = await client.SendEmailAsync("1469", "your-api-key", new EmailData
{
Recipients = new List<string> { "[email protected]", "[email protected]" },
Subject = "Important School Update",
Body = "<h1>Update</h1><p>School will start 1 hour late tomorrow due to weather.</p>",
FromName = "School Office",
FromAddress = "[email protected]",
ClientRef = "UPDATE-001",
CallbackUrl = "https://your-app.com/email-callback"
});
Email Best Practices
HTML Email Guidelines
- Use inline CSS for better email client compatibility
- Test across clients (Outlook, Gmail, Apple Mail, etc.)
- Include alt text for images
- Provide plain text fallback when possible
Content Best Practices
- Clear subject lines that describe the content
- Concise messaging - get to the point quickly
- Mobile-friendly design with responsive layouts
- Accessible content with proper headings and contrast
Delivery Optimization
- Validate email addresses before sending
- Monitor bounce rates and remove invalid addresses
- Use delivery callbacks to track success/failure
- Implement retry logic for temporary failures
Error Handling
Common Email Errors
Invalid Email Address
{
"WarningMessages": ["Invalid email address: invalid-email-format"],
"errorMsg": "No recipients with valid addresses",
"MessageSentId": 0,
"MessageId": null
}
Missing Required Fields
{
"WarningMessages": [],
"errorMsg": "EmailSubject is required",
"MessageSentId": 0,
"MessageId": null
}
Authentication Errors
{
"WarningMessages": [],
"errorMsg": "Data is not valid, no messages sent",
"MessageSentId": 0,
"MessageId": null
}
Error Handling Example
try {
const result = await sendEmail(customerId, apiKey, emailData);
console.log('Email sent successfully:', result.messageId);
} catch (error) {
if (error.message.includes('No recipients with valid addresses')) {
console.error('Invalid email addresses provided');
// Handle invalid email addresses
} else if (error.message.includes('Data is not valid')) {
console.error('Authentication failed');
// Handle authentication error
} else {
console.error('Email sending failed:', error.message);
// Handle other errors
}
}
Next Steps:
- Learn about Recipients Reference for advanced targeting
- Explore SMS API Guide for text message sending
- Learn about Authentication methods
- Set up Delivery Tracking with callbacks
- Review Error Handling best practices