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: