Skip to main content

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

FieldTypeDescriptionExample
CustomerIdStringYour customer account ID"1469"
PasswordStringCustomer API key"your-api-key"
RecipientsArrayList of email recipient objects (see Recipients Reference)[{"EmailAddress": "[email protected]"}]
EmailSubjectStringEmail subject line"Important Update"
EmailBodyStringEmail content (HTML or plain text)"<p>Hello!</p>"

Optional Fields

FieldTypeDescriptionExample
ClientRefStringYour reference for tracking"EMAIL-001"
CallbackUrlStringURL for delivery status updates"https://app.com/callback"
EmailSentFromNameStringSender display name"School Office"
EmailSentFromAddressStringSender email address"[email protected]"
EmailReplyToAddressStringReply-to email address"[email protected]"
AttachmentsArrayList 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: