xiigroup / ucgateway
Official PHP Integration SDK for XII Group UC Gateway
Requires
- php: >=7.4
- ext-curl: *
- ext-json: *
Requires (Dev)
- phpunit/phpunit: ^9.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
π UC Gateway API
Official Integration SDK & Technical Specification for XII Group UC Gateway
A unified, stateful HTTP interface for sending WhatsApp, MoyaApp and SMS communications.
Key Features β’ Quick Start β’ Whatsapp API β’ Moya API β’ SMS API β’ Webhooks & Security β’ Stateful Chatbots β’ Support
π Overview
UC Gateway simplifies multi-channel messaging by exposing a single endpoint to handle WhatsApp, MoyaApp and SMS. It features a built-in state engine for serverless, persistent chatbot integrationsβeliminating the need for external caching layers like Redis for basic conversational flows.
βββββββββββββββββββ
β Your App / β
β Serverless Bot β
ββββββββββ¬βββββββββ
β
HTTPS POST β Incoming Webhook
(Send Payload) β (With Raw HMAC)
βΌ
βββββββββββββββββββ
β UC Gateway β
ββββββββββ¬βββββββββ
β
ββββββββββββββββββββββββ|ββββββββββββββββββββββββ
βΌ βΌ βΌ
π’ WhatsApp Cloud π΅ MoyaApp π‘ SMS Telco Network
β¨ Key Features
- Unified Messaging Interface: Send text, templates, interactive lists, CTA links, quick reply buttons, media, and locations across WhatsApp, MoyaApp & SMS.
- Built-in Chatbot State & Memory: Native
stateandmemoryobjects returned inside webhooks to easily maintain user sessions. - Synchronous Webhook Replies: Respond directly to an incoming webhook with a
200 OKJSON payload to issue an instant messaging reply. - Granular Webhook Separation: Independent endpoints for incoming messages vs. Delivery Receipts (DLR / Statuses).
- HMAC SHA-256 Webhook Security: Enterprise-grade signature verification over raw request payloads.
βοΈ Base Configuration
| Parameter | Value |
|---|---|
| Base URL | https://uc-api.xiigroup.co.za/ |
| Current API Version | v1.0 |
| Authentication | HTTP Basic Auth (Authorization: Basic <Base64(username:password)>) |
| Data Format | JSON (Content-Type: application/json) |
β οΈ Note: WhatsApp, MoyaApp and SMS use separate credentials and separate portal-configured Number IDs (
nid).
π Quick Start
π¦ SDK Installation
PHP
Install via Composer:
composer require xiigroup/ucgateway
Node.js / TypeScript
Install via npm or yarn:
npm install @xiigroup/ucgateway
# or
yarn add @xiigroup/ucgateway
π» SDK Initialization & Usage
PHP SDK
<?php require_once __DIR__ . '/vendor/autoload.php'; use Xiigroup\UcGateway\UcGatewayClient; // Initialize the SDK client $client = new UcGatewayClient( username: 'YOUR_API_USERNAME', password: 'YOUR_API_PASSWORD' ); // Plain Text (Optionally pass $msgId to send a direct reply) $client->sendWhatsAppText( nid: 12345678, to: '27716629021', body: 'Hello from UC Gateway PHP SDK!', // msgId: 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA', //uncomment to send reply to previous message ); // Template Message $client->sendWhatsAppTemplate( nid: 12345678, to: '27716629021', name: 'welcome_template', language: 'en', header: [['text' => 'Welcome']], body: [['text' => 'John']] ); // Quick Reply Buttons $client->sendWhatsAppButtons( nid: 12345678, to: '27716629021', body: 'How can we assist you today?', buttons: ['Billing Inquiry', 'Technical Support'], header: 'Support Desk', footer: 'Automated Helpdesk', // msgId: 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA', ); // Interactive List $client->sendWhatsAppList( nid: 12345678, to: '27716629021', body: 'Please choose an option below:', listItems: [ 'Option 1 Description' => 'Option 1', 'Option 2 Description' => 'Option 2' ], label: 'Select Option', header: 'Main Menu', footer: 'XII Group', // msgId: 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA', ); // Media (image, video, audio, document) $client->sendWhatsAppMedia( nid: 12345678, to: '27716629021', type: 'image', mediaUrl: 'https://domain.com/assets/banner.jpg', caption: 'Check out our latest release!', // msgId: 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA', ); // Send Location $client->sendWhatsAppLocation( nid: 12345678, to: '27716629021', longitude: '28.422152', latitude: '-25.723444', // msgId: 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA', ); // Request Location $client->requestWhatsAppLocation( nid: 12345678, to: '27716629021', body: 'Please share your location to proceed.', // msgId: 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA', ); // Mark Received Message as Read $client->markWhatsAppAsRead( nid: 12345678, msgId: 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA', );
$smsClient = new Xiigroup\UcGateway\UcGatewayClient(
username: 'YOUR_SMS_USERNAME',
password: 'YOUR_SMS_PASSWORD'
);
// Plain Text
$client->sendMoyaAppText(
nid: 12345678,
to: '27716629021',
body: 'Hello from UC Gateway PHP SDK!',
);
// Quick Reply Buttons
$client->sendMoyaAppButtons(
nid: 12345678,
to: '27716629021',
body: 'How can we assist you today?',
buttons: ['Billing Inquiry', 'Technical Support']
);
$smsClient = new Xiigroup\UcGateway\UcGatewayClient(
username: 'YOUR_SMS_USERNAME',
password: 'YOUR_SMS_PASSWORD'
);
$smsClient->sendSms(
nid: 12345678,
to: '27670826044',
body: 'Your verification code is: 4829'
);
TypeScript / Node.js SDK
import { UcGatewayClient } from '@xiigroup/ucgateway'; // Initialize the SDK client const client = new UcGatewayClient({ username: process.env.UC_API_USERNAME!, password: process.env.UC_API_PASSWORD! }); async function sendWhatsAppExamples() { const nid = 12345678; const to = '27716629021'; // Plain Text (Optionally pass msgId to reply directly) await client.sendWhatsAppText(nid, to, 'Hello from UC Gateway Node.js SDK!'); // Template Message await client.sendWhatsAppTemplate( nid, to, 'welcome_template', 'en', [{ text: 'Welcome' }], [{ text: 'John' }] ); // Quick Reply Buttons await client.sendWhatsAppButtons( nid, to, 'How can we assist you today?', ['Billing Inquiry', 'Technical Support'], 'Support Desk', 'Automated Helpdesk', // 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA' //uncomment to send reply to previous message ); // Interactive List await client.sendWhatsAppList( nid, to, 'Please choose an option below:', { 'Option 1 Description': 'Option 1', 'Option 2 Description': 'Option 2' }, { label: 'Select Option', header: 'Main Menu', footer: 'XII Group' }, // 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA' ); // Call To Action (CTA) Link await client.sendWhatsAppCTA( nid, to, 'https://xiigroup.co.za', 'Click the link below to visit our website', { header: 'XII Group', footer: 'Official Portal' }, // 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA' ); // Media (image, video, audio, document, sticker) await client.sendWhatsAppMedia( nid, to, 'image', 'https://domain.com/assets/banner.jpg', 'Check out our latest release!', // 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA' ); // Send Location Coordinates await client.sendWhatsAppLocation( nid, to, -25.7479, 28.2293, 'XII Group HQ', 'Pretoria, South Africa', // 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA' ); // Request Location await client.requestWhatsAppLocation( nid, to, 'Please share your location to proceed.', // 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA' ); // Pinpad / Dialpad Interactive Interface await client.sendWhatsAppKeypad( nid, to, 'Enter your 4-digit PIN code:', 'pinpad', // 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJCM0I3QjFGRUNDRTVGMUREMjkA' ); // Mark Received Message as Read await client.markWhatsAppAsRead(nid, 'wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJEOTAzMDUyNzZCNUVFNzg1RDkA'); }
const smsClient = new UcGatewayClient({
username: process.env.UC_SMS_USERNAME!,
password: process.env.UC_SMS_PASSWORD!
});
async function sendSmsExample() {
await smsClient.sendSms(
12345678,
'27670826044',
'Your verification code is: 4829'
);
}
π Direct HTTP / cURL Example
1. Send WhatsApp Text Message (cURL)
curl -X POST "https://uc-api.xiigroup.co.za/" \ -u "username:password" \ -H "Content-Type: application/json" \ -H "HTTP_API_VERSION: v1.0" \ -d '{ "endpoint": "whatsapp", "action": "send", "type": "text", "nid": 12345678, "to": "27716629021", "body": "Hello from UC Gateway!" }'
2. Send Moya Message (cURL)
curl -X POST "https://uc-api.xiigroup.co.za/" \ -u "moyaapp_username:moyaapp_password" \ -H "Content-Type: application/json" \ -H "HTTP_API_VERSION: v1.0" \ -d '{ "endpoint": "moyaapp", "action": "send", "nid": 12345678, "to": "27670826044", "body": "Your verification code is: 4829" }'
3. Send SMS Message (cURL)
curl -X POST "https://uc-api.xiigroup.co.za/" \ -u "sms_username:sms_password" \ -H "Content-Type: application/json" \ -H "HTTP_API_VERSION: v1.0" \ -d '{ "endpoint": "sms", "action": "send", "nid": 12345678, "to": "27670826044", "body": "Your verification code is: 4829" }'
π¬ WhatsApp API
Below are the JSON payload structures for various WhatsApp message types supported by the gateway.
1. Template Message
Used to send pre-approved transactional or promotional WhatsApp templates containing header and body variable parameters.
{
"endpoint": "whatsapp",
"action": "send",
"type": "template",
"nid": 12345678,
"to": "27716629021",
"name": "welcome_template",
"language": "en",
"header": [
{ "text": "Welcome" }
],
"body": [
{ "text": "John" }
]
}
2. Interactive List Message
Displays a menu button (label) that opens a structured list of selectable options with titles and descriptions.
{
"endpoint": "whatsapp",
"action": "send",
"type": "list",
"nid": 12345678,
"to": "27716629021",
"label": "Select Option",
"header": "Main Menu",
"body": "Please choose an option below:",
"footer": "XII Group",
"list": {
"Option 1 Description": "Option 1",
"Option 2 Description": "Option 2"
}
}
3. Quick Reply Buttons Message
Sends an interactive message with up to 3 quick reply action buttons for fast user responses.
{
"endpoint": "whatsapp",
"action": "send",
"type": "buttons",
"nid": 12345678,
"to": "27716629021",
"header": "Support Desk",
"body": "How can we assist you today?",
"footer": "Automated Helpdesk",
"button": [
"Billing Inquiry",
"Technical Support"
]
}
4. Media Message (Image / Document / Audio / Video)
Sends hosted media files via a direct URL link with an optional caption text body.
{
"endpoint": "whatsapp",
"action": "send",
"type": "image",
"nid": 12345678,
"to": "27716629021",
"link": "https://domain.com/assets/banner.jpg",
"body": "Check out our latest release!"
}
5. Send Location Message
Send whatsapp location.
{
"endpoint": "whatsapp",
"action": "send",
"type": "location",
"nid": 12345678,
"to": "27716629021",
"longitude": "28.422152",
"latitude": "-25.723444"
}
6. Request Location Message
Request whatsapp location.
{
"endpoint": "whatsapp",
"action": "send",
"type": "location_request",
"nid": 12345678,
"to": "27716629021",
"body": "Send your location"
}
7. Direct Message Reply
Replies directly to a previously received incoming message by referencing its unique WhatsApp Message ID (msg_id).
{
"endpoint": "whatsapp",
"action": "send",
"type": "text",
"nid": 12345678,
"to": "27716629021",
"body": "This is a direct reply",
"msg_id": "wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJEOTAzMDUyNzZCNUVFNzg1RDkA"
}
8. Mark message as read
Mark received message as Read by sending Whatsapp Message ID in msg_id field.
{
"endpoint": "whatsapp",
"action": "send",
"type": "read",
"nid": 12345678,
"msg_id": "wamid.HBgLMjc3MTY2MjkwMjEVAgARGBJEOTAzMDUyNzZCNUVFNzg1RDkA"
}
π‘ MoyaApp API
1. Quick Reply Buttons Message
Sends an interactive message with up to 3 quick reply action buttons for fast user responses. does not support header, footer & msg_id.
{
"endpoint": "moyaapp",
"action": "send",
"type": "buttons",
"nid": 12345678,
"to": "27716629021",
"body": "How can we assist you today?",
"button": [
"Billing Inquiry",
"Technical Support"
]
}
2. Request Location Message
Request MoyaApp location. type can be set to location_request or gps_location_request
{
"endpoint": "moyaapp",
"action": "send",
"type": "location_request", //gps_location_request
"nid": 12345678,
"to": "27716629021",
"body": "Send your location"
}
3. Media Message (Image / Document / Audio / Video)
Sends hosted media files via a direct URL link with an optional caption text body.
{
"endpoint": "moyaapp",
"action": "send",
"type": "image",
"nid": 12345678,
"to": "27716629021",
"link": "https://domain.com/assets/banner.jpg",
"body": "Check out our latest release!"
}
π‘ SMS API
Outgoing SMS Payload
To send an SMS, set "endpoint": "sms" and supply the standard dispatch fields:
{
"endpoint": "sms",
"action": "send",
"nid": 12345678,
"to": "27670826044",
"body": "Your verification code is: 4829"
}
Incoming SMS Webhook Payload
Incoming SMS messages are delivered to your portal-configured SMS webhook as type="text":
{
"id": "b27e8723-b8bb-4604-0109-09140000a61d",
"mo_msg_id": "18361924",
"charset": "UTF-8",
"type": "text",
"sender": "27990794903081",
"from": "27603166427",
"name": "Guest",
"message": "Hi",
"state": 1,
"memory": []
}
SMS Delivery Receipt (DLR / Status Webhook)
Status updates regarding outbound SMS delivery are dispatched asynchronously to your SMS status webhook:
{
"id": "1789370565",
"platform": "sms",
"status": "delivered",
"recipient_id": "27603166427",
"timestamp": "1789372457"
}
βοΈ WhatsApp vs. MoyaApp vs. SMS Feature Comparison
| Feature | MoyaApp | SMS | |
|---|---|---|---|
| API Version | v1.0 |
v1.0 |
v1.0 |
| Endpoint Parameter | whatsapp |
moyaapp |
sms |
| Credentials | WhatsApp API Credentials | MoyaApp API Credentials | SMS API Credentials |
| Supported Message Types | text, templates, lists, cta, buttons, image, document, audio, video, location, location_request, keypad, pinpad | text, image, document, audio, video, location_request, gps_location_request | text |
| Supported DLR Statuses | sent, delivered, read |
sent, delivered, read, failed |
sent, delivered, undelivered, queued, failed |
| Webhooks | Configured via WhatsApp Portal Settings | Configured via MoyaApp Portal Settings | Configured via SMS Portal Settings |
| Stateful Engine | Native state & memory |
Native state & memory |
Native state & memory |
π Webhooks & Signature Validation
Incoming webhooks include the following authentication headers for verification:
| Header | Description |
|---|---|
X-Uc-Signature |
Calculated HMAC SHA-256 signature string |
X-Uc-Nonce |
32-character random nonce string |
X-Uc-Timestamp |
Unix epoch timestamp of request execution |
Signature Algorithm
The gateway signs the entire raw JSON request body using HMAC SHA-256 with your portal shared secret: $$\text{Signature} = \text{HMAC-SHA256}(\text{SharedSecret}, \text{RawRequestBody})$$
Implementation Examples
PHP Signature Validation
<?php // 1. Fetch raw request body & signature header $rawPayload = file_get_contents('php://input'); $incomingSignature = $_SERVER['HTTP_X_UC_SIGNATURE'] ?? ''; $secret = 'YOUR_PORTAL_SHARED_SECRET'; // 2. Compute HMAC SHA-256 hash $calculatedSignature = hash_hmac('sha256', $rawPayload,$secret); // 3. Constant-time string comparison if (hash_equals($calculatedSignature,$incomingSignature)) { http_response_code(200); echo json_encode(["status" => "validated"]); } else { http_response_code(401); exit("Invalid Webhook Signature"); }
Node.js (Express) Signature Validation
const express = require('express'); const crypto = require('crypto'); const app = express(); app.use(express.raw({ type: 'application/json' })); // Capture raw body bytes app.post('/webhook', (req, res) => { const secret = 'YOUR_PORTAL_SHARED_SECRET'; const incomingSignature = req.headers['x-uc-signature']; const rawPayload = req.body.toString('utf8'); const calculatedSignature = crypto .createHmac('sha256', secret) .update(rawPayload) .digest('hex'); if (crypto.timingSafeEqual(Buffer.from(calculatedSignature), Buffer.from(incomingSignature))) { res.status(200).send({ status: 'validated' }); } else { res.status(401).send('Invalid Signature'); } });
π€ Stateful Chatbot Engine
UC Gateway automatically passes user conversational context inside incoming webhook payloads using the state and memory parameters.
Incoming Webhook Structure
{
"id": "wamid.HBgLMjc3MTY2MjkwMjEVAgASGCBBQ0Q3N0M0M0EyNEEyMkZFQTdBQTkwQ0QxQjA5NUFGNQA=",
"sender": "27128801496",
"from": "27716629021",
"name": "Jane Doe",
"type": "text",
"message": "Start",
"state": "MAIN_MENU",
"memory": {
"user_id": 482,
"cart": []
}
}
Instant Synchronous Webhook Response
If your server acts as an automated bot, you can return a 200 OK HTTP response containing updated state data. UC Gateway will automatically route the message reply back to the end-user:
{
"state": "AWAITING_SELECTION",
"message": "Welcome back, Jane! Please select an option from the menu.",
"memory": {
"user_id": 482,
"last_seen": "2026-09-14"
},
"api": null,
"error": null
}
π¦ HTTP Status Code Reference
| Code | Status | Meaning |
|---|---|---|
200 |
OK | Request accepted and processed successfully. |
400 |
Bad Request | Validation failure or missing mandatory parameters (to, nid, endpoint). |
401 |
Unauthorized | Authentication header failure or invalid API credentials. |
429 |
Rate Limited | API quota or rate limit thresholds exceeded. |
500 |
Server Error | Gateway processing failure. Contact support. |
π€ Author & Support
-
Author: Sipho Selabe
-
Email: sg.selabe@xiigroup.co.za
-
Organization: XII Group
-
GitHub Repository: xiigroup