Skip to main content

Authentication Code Examples

Complete code examples for implementing both authentication methods with the Communications API.

Customer Authentication Examples

Customer authentication uses dedicated credentials for each organization you integrate with.

JavaScript/Node.js

Basic Implementation

const axios = require('axios');

class CommunicationsClient {
constructor(customerId, apiKey) {
this.customerId = customerId;
this.apiKey = apiKey;
this.API_BASE = 'https://m5api.groupcall.com';
}

async sendSMS(recipients, message, options = {}) {
const payload = {
messageData: [{
CustomerId: this.customerId,
Password: this.apiKey,
Recipients: Array.isArray(recipients) ? recipients : [recipients],
SMSMessage: message,
...options
}]
};

try {
const response = await axios.post(
`${this.API_BASE}/api/SendMessage_V3/SMS`,
payload,
{ headers: { 'Content-Type': 'application/json' } }
);

return this.handleResponse(response.data);
} catch (error) {
throw new Error(`SMS sending failed: ${error.message}`);
}
}

handleResponse(response) {
if (!Array.isArray(response) || response.length === 0) {
throw new Error('Invalid response format');
}

const result = response[0];

if (result.errorMsg && result.errorMsg.startsWith('OK') && result.MessageId) {
return {
success: true,
messageId: result.MessageId,
status: result.statusMsg,
transmitDateTime: result.transmitDateTime
};
}

const errorMsg = result.errorMsg ||
(result.WarningMessages && result.WarningMessages[0]) ||
'Unknown error';

throw new Error(errorMsg);
}
}

// Usage
const client = new CommunicationsClient('your-customer-id', 'your-api-key');

client.sendSMS('+447700900123', 'Hello from our school!')
.then(result => console.log('Message sent:', result))
.catch(error => console.error('Error:', error.message));

With Async/Await and Error Handling

async function sendMessageWithRetry(client, recipients, message, maxRetries = 3) {
let attempt = 0;

while (attempt < maxRetries) {
try {
const result = await client.sendSMS(recipients, message);
return result;
} catch (error) {
attempt++;

if (error.message.includes('Data is not valid')) {
// Auth error - don't retry
throw error;
}

if (attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}

throw new Error(`Failed after ${maxRetries} attempts`);
}

Python

Basic Implementation

import requests
import json
from typing import List, Dict, Optional

class CommunicationsClient:
def __init__(self, customer_id: str, api_key: str):
self.customer_id = customer_id
self.api_key = api_key
self.API_BASE = 'https://m5api.groupcall.com'

def send_sms(self, recipients: List[str], message: str, **options) -> Dict:
"""Send SMS message to recipients"""
payload = {
"messageData": [{
"CustomerId": self.customer_id,
"Password": self.api_key,
"Recipients": recipients,
"SMSMessage": message,
**options
}]
}

response = requests.post(
f"{self.API_BASE}/api/SendMessage_V3/SMS",
headers={'Content-Type': 'application/json'},
json=payload
)

response.raise_for_status()
return self._handle_response(response.json())

def _handle_response(self, response: List[Dict]) -> Dict:
"""Handle API response and extract result"""
if not response or not isinstance(response, list):
raise ValueError('Invalid response format')

result = response[0]

if (result.get('errorMsg', '').startswith('OK') and
result.get('MessageId')):
return {
'success': True,
'message_id': result['MessageId'],
'status': result.get('statusMsg'),
'transmit_date_time': result.get('transmitDateTime')
}

error_msg = (result.get('errorMsg') or
(result.get('WarningMessages') and result['WarningMessages'][0]) or
'Unknown error')

raise Exception(f"Message sending failed: {error_msg}")

# Usage
client = CommunicationsClient('your-customer-id', 'your-api-key')

try:
result = client.send_sms(
recipients=['+447700900123'],
message='Hello from our school!',
callbackUrl='https://your-app.com/sms-callback'
)
print(f"Message sent successfully: {result}")
except Exception as e:
print(f"Error sending message: {e}")

With Context Manager and Logging

import logging
from contextlib import contextmanager

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class CommunicationsClient:
# ... previous implementation ...

@contextmanager
def message_session(self):
"""Context manager for message sending session"""
logger.info("Starting message session")
try:
yield self
except Exception as e:
logger.error(f"Message session failed: {e}")
raise
finally:
logger.info("Message session completed")

# Usage with context manager
client = CommunicationsClient('your-customer-id', 'your-api-key')

with client.message_session() as session:
result = session.send_sms(['+447700900123'], 'Test message')
logger.info(f"Message sent: {result['message_id']}")

C#

Basic Implementation

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class CommunicationsClient
{
private readonly HttpClient _httpClient;
private readonly string _customerId;
private readonly string _apiKey;
private const string API_BASE = "https://m5api.groupcall.com";

public CommunicationsClient(string customerId, string apiKey)
{
_customerId = customerId ?? throw new ArgumentNullException(nameof(customerId));
_apiKey = apiKey ?? throw new ArgumentNullException(nameof(apiKey));
_httpClient = new HttpClient();
}

public async Task<MessageResult> SendSmsAsync(
string[] recipients,
string message,
string callbackUrl = null)
{
var payload = new
{
messageData = new[]
{
new
{
CustomerId = _customerId,
Password = _apiKey,
Recipients = recipients,
SMSMessage = message,
CallbackUrl = callbackUrl
}
}
};

var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");

var response = await _httpClient.PostAsync($"{API_BASE}/api/SendMessage_V3/SMS", content);
var responseContent = await response.Content.ReadAsStringAsync();

return HandleResponse(responseContent);
}

private MessageResult HandleResponse(string responseJson)
{
var responses = JsonSerializer.Deserialize<ApiResponse[]>(responseJson);

if (responses == null || responses.Length == 0)
{
throw new InvalidOperationException("Invalid response format");
}

var result = responses[0];

if (!string.IsNullOrEmpty(result.ErrorMsg) &&
result.ErrorMsg.StartsWith("OK") &&
!string.IsNullOrEmpty(result.MessageId))
{
return new MessageResult
{
Success = true,
MessageId = result.MessageId,
Status = result.StatusMsg,
TransmitDateTime = result.TransmitDateTime
};
}

var errorMsg = result.ErrorMsg ??
(result.WarningMessages?.Length > 0 ? result.WarningMessages[0] : "Unknown error");

throw new Exception($"Message sending failed: {errorMsg}");
}

public void Dispose()
{
_httpClient?.Dispose();
}
}

// Supporting classes
public class ApiResponse
{
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 string TransmitDateTime { get; set; }
public string ClientRef { get; set; }
}

public class MessageResult
{
public bool Success { get; set; }
public string MessageId { get; set; }
public string Status { get; set; }
public string TransmitDateTime { get; set; }
}

// Usage
var client = new CommunicationsClient("your-customer-id", "your-api-key");

try
{
var result = await client.SendSmsAsync(
new[] { "+447700900123" },
"Hello from our school!",
"https://your-app.com/sms-callback"
);

Console.WriteLine($"Message sent successfully: {result.MessageId}");
}
catch (Exception ex)
{
Console.WriteLine($"Error sending message: {ex.Message}");
}
finally
{
client.Dispose();
}

With Dependency Injection and Logging

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

public interface ICommunicationsClient
{
Task<MessageResult> SendSmsAsync(string[] recipients, string message, string callbackUrl = null);
}

public class CommunicationsClient : ICommunicationsClient, IDisposable
{
private readonly HttpClient _httpClient;
private readonly CommunicationsOptions _options;
private readonly ILogger<CommunicationsClient> _logger;

public CommunicationsClient(
HttpClient httpClient,
IOptions<CommunicationsOptions> options,
ILogger<CommunicationsClient> logger)
{
_httpClient = httpClient;
_options = options.Value;
_logger = logger;
}

public async Task<MessageResult> SendSmsAsync(string[] recipients, string message, string callbackUrl = null)
{
_logger.LogInformation("Sending SMS to {RecipientCount} recipients", recipients.Length);

try
{
// Implementation same as above
var result = await SendSmsInternalAsync(recipients, message, callbackUrl);

_logger.LogInformation("SMS sent successfully: {MessageId}", result.MessageId);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to send SMS");
throw;
}
}

// ... rest of implementation
}

public class CommunicationsOptions
{
public string CustomerId { get; set; }
public string ApiKey { get; set; }
public string ApiBase { get; set; } = "https://m5api.groupcall.com";
}

Partner Authentication Examples

Partner authentication allows managing multiple customers with a single partner account.

Coming Soon

Partner authentication examples will be added once the partner authentication guide is completed. These examples will show how to:

  • Receive customer authorization callbacks
  • Store and manage multiple customer credentials
  • Send messages on behalf of different customers
  • Handle partner-specific authentication flows

Testing and Validation

Authentication Test Function

async function testAuthentication(customerId, apiKey) {
const API_BASE = 'https://m5api.groupcall.com';
const testPayload = {
messageData: [{
CustomerId: customerId,
Password: apiKey,
Recipients: [
{ MobileNumber: "+447700900000" } // Invalid test number
],
SMSMessage: "Authentication test"
}]
};

try {
const response = await fetch(`${API_BASE}/api/SendMessage_V3/SMS`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(testPayload)
});

const result = await response.json();

if (result[0].errorMsg === "Data is not valid, no messages sent") {
return { valid: false, error: 'Invalid credentials' };
} else if (result[0].WarningMessages?.includes("No recipients with valid addresses")) {
return { valid: true, message: 'Credentials are valid' };
} else {
return { valid: false, error: 'Unexpected response', result };
}
} catch (error) {
return { valid: false, error: `Network error: ${error.message}` };
}
}

// Usage
const authTest = await testAuthentication('your-customer-id', 'your-api-key');
console.log('Authentication test:', authTest);

Error Handling Patterns

Comprehensive Error Handler

class CommunicationsError extends Error {
constructor(message, code, response) {
super(message);
this.name = 'CommunicationsError';
this.code = code;
this.response = response;
}
}

function handleApiError(response) {
const result = response[0];

if (result.errorMsg === "Data is not valid, no messages sent") {
throw new CommunicationsError(
'Invalid authentication credentials',
'AUTH_INVALID',
result
);
}

if (result.WarningMessages?.includes("Customer does not allow sending SMS")) {
throw new CommunicationsError(
'Customer account does not have SMS permissions',
'PERMISSION_DENIED',
result
);
}

if (result.WarningMessages?.includes("No recipients with valid addresses")) {
throw new CommunicationsError(
'All recipient phone numbers are invalid',
'INVALID_RECIPIENTS',
result
);
}

const errorMsg = result.errorMsg ||
(result.WarningMessages && result.WarningMessages[0]) ||
'Unknown error';

throw new CommunicationsError(errorMsg, 'UNKNOWN_ERROR', result);
}

Related Documentation: