GENIQ REST API Reference

Welcome to the GENIQ Cloud Communications developer reference. Our APIs allow you to deliver global SMS marketing messages and secure multi-factor validation codes instantly over carrier networks.

This portal describes the REST structures, parameter definitions, and response behavior. All endpoints are secured via HTTPS, returning JSON response envelopes standardly.

đź’ˇ Base Server URL

https://api.geniq.io/rest/v1
GENIQ REST API Base
// All requests are made via HTTPS.
// Data is passed as URL-encoded form parameters or query strings.
// Responses are returned standardly in JSON.
{
  "responseCode": "0",
  "responseMessage": "Success"
}

Authentication

All API requests sent to GENIQ servers require authentication. First, authenticate using your API key and secret via HTTP Basic Auth to get a temporary access token. Subsequently, pass this token in the header of each request using the Bearer token scheme.

Before generating the access token, you must first access our console to create an API key and secret. Once generated, combine them in the format API_KEY:SECRET, encode it in Base64, and pass it in the Authorization: Basic [BASE64] header of the token request.

API Authorization Schemes

Scheme Header Format Usage
Basic Auth Authorization: Basic [BASE64_KEY_SECRET] Used solely on the /token endpoint to request an access token.
Bearer Token Authorization: Bearer [TOKEN] Used on all other resource endpoints (SMS, OTP, Balance, etc.).
Authentication Flow
// Step 1: Request Access Token
POST /rest/v1/token HTTP/1.1
Authorization: Basic Base64(API_KEY:SECRET)

// Step 2: Use Access Token for API Requests
POST /rest/v1/sms HTTP/1.1
Authorization: Bearer [TOKEN]
POST /token

Request Access Token

Generate a temporary JWT access token using your API key credentials. The returned token should be cached and reused for all subsequent API requests until it expires.

Headers Required

Header Required Value
Authorization Yes Basic [BASE64_API_KEY_AND_SECRET]

Response Fields

Field Format Description
token string The generated JWT access token to use for Bearer authentication.
expiry string Token expiry timestamp in RFC3339 format (Y-m-d\TH:i:sP).
responseCode integer Response code. 0 indicating success.
responseMessage string Response message from the server.
curl -X POST https://api.geniq.io/rest/v1/token \
  -H 'Authorization: Basic YW55LWtleTpzZWNyZXQ='`
const axios = require('axios');
const key = 'YOUR_API_KEY';
const secret = 'YOUR_API_SECRET';
const basicAuth = Buffer.from(`${key}:${secret}`).toString('base64');

axios.post('https://api.geniq.io/rest/v1/token', {}, {
  headers: { 'Authorization': `Basic ${basicAuth}` }
})
.then(res => console.log(res.data));
import requests
key = "YOUR_API_KEY"
secret = "YOUR_API_SECRET"

response = requests.post(
    'https://api.geniq.io/rest/v1/token',
    auth=(key, secret)
)
print(response.json())
package main
import (
	"fmt"
	"io"
	"net/http"
)
func main() {
	req, _ := http.NewRequest("POST", "https://api.geniq.io/rest/v1/token", nil)
	req.SetBasicAuth("YOUR_API_KEY", "YOUR_SECRET")
	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
JSON Response (200 OK)
{
  "expiry": "2024-12-11T16:14:46+08:00",
  "responseMessage": "Success",
  "responseCode": "0",
  "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signature"
}
POST /sms

Send SMS Message

Submit request parameters to queue a text message for sending to a single recipient mobile number.

Request Parameters

Field Type Required Description
recipient integer Yes Recipient's mobile number including country code without "+" prefix (e.g. 6591234567).
originator string Yes The originator address/Sender ID for the outgoing SMS (e.g. GENIQ). Alphanumeric max 11 characters.
message string Yes Body of the SMS message. Supports UTF-8. 160 characters equals 1 SMS segment.
reference string No A unique reference ID to track requests and match responses/callbacks.
originatorTon string No Type of number (TON): auto (default), national, alpha, international.
udh string No User Data Header (hex-encoded string) for binary or concatenated SMS.
dataCoding string No Data coding option: auto (default), text (GSM 03.38), or unicode.
validity integer No Relative validity time in seconds. Discarded if not delivered within this window.

Response Fields

Field Format Description
reference string The unique reference submitted in the request, or empty.
responseCode integer Status code from the API. 0 indicating success.
responseMessage string Description message corresponding to the response code.
messageIds array List of unique UUID string message IDs generated for each segment of the sent SMS.
curl -X POST https://api.geniq.io/rest/v1/sms \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -d "recipient=6591234567" \
  -d "originator=Hello" \
  -d "message=Test message from GENIQ" \
  -d "reference=12345"
const axios = require('axios');
const qs = require('qs');

axios.post('https://api.geniq.io/rest/v1/sms', qs.stringify({
  recipient: '6591234567',
  originator: 'Hello',
  message: 'Test message from GENIQ',
  reference: '12345'
}), {
  headers: { 
    'Authorization': 'Bearer YOUR_TOKEN',
    'Content-Type': 'application/x-www-form-urlencoded'
  }
})
.then(res => console.log(res.data));
import requests
url = 'https://api.geniq.io/rest/v1/sms'
payload = {
    'recipient': '6591234567',
    'originator': 'Hello',
    'message': 'Test message from GENIQ',
    'reference': '12345'
}
headers = {
    'Authorization': 'Bearer YOUR_TOKEN',
    'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.post(url, data=payload, headers=headers)
print(response.json())
package main
import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
)
func main() {
	data := url.Values{}
	data.Set("recipient", "6591234567")
	data.Set("originator", "Hello")
	data.Set("message", "Test message from GENIQ")
	data.Set("reference", "12345")

	req, _ := http.NewRequest("POST", "https://api.geniq.io/rest/v1/sms", strings.NewReader(data.Encode()))
	req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
JSON Response (200 OK)
{
  "reference": "12345",
  "responseMessage": "Success",
  "responseCode": "0",
  "messageIds": [
    "e36ba3b8-db55-4eef-99e4-79f3e2422846"
  ]
}
POST /batch_sms

Send Batch SMS

Submit request parameters to queue a text message for sending to multiple recipient mobile numbers at once. Numbers should be comma-separated.

Request Parameters

Field Type Required Description
recipients string Yes Comma-separated list of recipient mobile numbers including country code without "+" prefix (e.g. 6591234567,6581234567).
originator string Yes The originator address/Sender ID for the outgoing SMS. Alphanumeric max 11 characters.
message string Yes Body of the SMS message. Supports UTF-8.
reference string No A unique reference ID to track requests and match responses.
originatorTon string No Type of number (TON): auto (default), national, alpha, international.
udh string No User Data Header (hex-encoded string) for binary or concatenated SMS.
dataCoding string No Data coding option: auto (default), text (GSM 03.38), or unicode.
validity integer No Relative validity time in seconds. Discarded if not delivered within this window.

Response Fields

Field Format Description
reference string The unique reference submitted in the request, or empty.
responseCode integer Status code from the API. 0 indicating success.
responseMessage string Description message corresponding to the response code.
details.total integer Total number of recipients in the batch request.
details.processed integer Total number of processed recipients.
details.failed integer Total number of failed recipients.
details.recipients[] array Array list containing recipient status blocks: recipient, messageIdList, responseCode, and responseMessage.
curl -X POST https://api.geniq.io/rest/v1/batch_sms \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -d "recipients=6591234567,6581234567" \
  -d "originator=Hello" \
  -d "message=Test batch message from GENIQ" \
  -d "reference=12345"
const axios = require('axios');
const qs = require('qs');

axios.post('https://api.geniq.io/rest/v1/batch_sms', qs.stringify({
  recipients: '6591234567,6581234567',
  originator: 'Hello',
  message: 'Test batch message from GENIQ',
  reference: '12345'
}), {
  headers: { 
    'Authorization': 'Bearer YOUR_TOKEN',
    'Content-Type': 'application/x-www-form-urlencoded'
  }
})
.then(res => console.log(res.data));
import requests
url = 'https://api.geniq.io/rest/v1/batch_sms'
payload = {
    'recipients': '6591234567,6581234567',
    'originator': 'Hello',
    'message': 'Test batch message from GENIQ',
    'reference': '12345'
}
headers = {
    'Authorization': 'Bearer YOUR_TOKEN',
    'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.post(url, data=payload, headers=headers)
print(response.json())
package main
import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
)
func main() {
	data := url.Values{}
	data.Set("recipients", "6591234567,6581234567")
	data.Set("originator", "Hello")
	data.Set("message", "Test batch message from GENIQ")
	data.Set("reference", "12345")

	req, _ := http.NewRequest("POST", "https://api.geniq.io/rest/v1/batch_sms", strings.NewReader(data.Encode()))
	req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
JSON Response (200 OK)
{
  "responseMessage": "Success",
  "responseCode": "0",
  "reference": "12345",
  "details": {
    "total": 2,
    "processed": 2,
    "failed": 0,
    "recipients": [
      {
        "recipient": "6591234567",
        "messageIdList": ["d6c5e5b9-847b-488a-bd93-c944ee26fafb"],
        "responseCode": "0",
        "responseMessage": "Success"
      },
      {
        "recipient": "6581234567",
        "messageIdList": ["a4c0bce2-0553-44c8-afde-8dada71e5e94"],
        "responseCode": "0",
        "responseMessage": "Success"
      }
    ]
  }
}
GET /balance

Check Account Balance

Query your current prepaid or postpaid balance amount and associated currency.

Response Fields

Field Format Description
currency string Currency code in ISO 4217 format (e.g. EUR, SGD).
type string Account billing scheme: Prepaid or Postpaid.
balance decimal Remaining financial balance amount.
responseCode integer Status code from the API. 0 indicating success.
responseMessage string Description message corresponding to the response code.
curl https://api.geniq.io/rest/v1/balance \
  -H 'Authorization: Bearer YOUR_TOKEN'
const axios = require('axios');

axios.get('https://api.geniq.io/rest/v1/balance', {
  headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
})
.then(res => console.log(res.data));
import requests

response = requests.get(
    'https://api.geniq.io/rest/v1/balance',
    headers={'Authorization': 'Bearer YOUR_TOKEN'}
)
print(response.json())
package main
import (
	"fmt"
	"io"
	"net/http"
)
func main() {
	req, _ := http.NewRequest("GET", "https://api.geniq.io/rest/v1/balance", nil)
	req.Header.Set("Authorization", "Bearer YOUR_TOKEN")

	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
JSON Response (200 OK)
{
  "currency": "EUR",
  "type": "Prepaid",
  "responseCode": "0",
  "balance": 19.2594,
  "responseMessage": "Success"
}
POST /verify

Send OTP SMS

Generate a One-Time Pin (OTP) code based on RFC6238 and transmit it directly to the recipient's mobile number via optimized SMS routes. An additional fee of €0.005 is charged per successful generation request.

Request Parameters

Field Type Required Description
recipient integer Yes Recipient's mobile number including country code without "+" prefix (e.g. 6591234567).
originator string Yes The originating address/Sender ID for the OTP SMS message.
reference string No A unique reference ID to track requests and responses.
template string No The template of the message body. Include the placeholder [CODE] for the actual generated OTP pin (e.g. "Your code is [CODE].").
codeLength integer No The number of digits in the verification code (between 6 and 8). Default is 6.
expiry integer No The verification code session validity time in seconds. Default is 30.

Response Fields

Field Format Description
reference string The unique reference submitted in the request, if any.
responseCode integer Status code from the API. 0 indicating success.
responseMessage string Description message corresponding to the response code.
messageIds array List containing the unique message ID string generated for the OTP SMS.
curl -X POST https://api.geniq.io/rest/v1/verify \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -d "recipient=6591234567" \
  -d "originator=Hello" \
  -d "reference=12345" \
  -d "expiry=300"
const axios = require('axios');
const qs = require('qs');

axios.post('https://api.geniq.io/rest/v1/verify', qs.stringify({
  recipient: '6591234567',
  originator: 'Hello',
  reference: '12345',
  expiry: 300
}), {
  headers: { 
    'Authorization': 'Bearer YOUR_TOKEN',
    'Content-Type': 'application/x-www-form-urlencoded'
  }
})
.then(res => console.log(res.data));
import requests
url = 'https://api.geniq.io/rest/v1/verify'
payload = {
    'recipient': '6591234567',
    'originator': 'Hello',
    'reference': '12345',
    'expiry': 300
}
headers = {
    'Authorization': 'Bearer YOUR_TOKEN',
    'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.post(url, data=payload, headers=headers)
print(response.json())
package main
import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
)
func main() {
	data := url.Values{}
	data.Set("recipient", "6591234567")
	data.Set("originator", "Hello")
	data.Set("reference", "12345")
	data.Set("expiry", "300")

	req, _ := http.NewRequest("POST", "https://api.geniq.io/rest/v1/verify", strings.NewReader(data.Encode()))
	req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
JSON Response (200 OK)
{
  "reference": "12345",
  "responseMessage": "Success",
  "responseCode": "0",
  "messageIds": [
    "62bf1beb-9451-40b5-9171-6f45f8935111"
  ]
}
POST /verify/{messageId}

Verifying OTP SMS

Submit the verification code received by the recipient along with the unique messageId previously returned during OTP generation.

Path / Query Parameters

Field Type Required Description
messageId string Yes (Path) A unique ID that was previously returned by our API when sending out the OTP SMS.
code string Yes (Query) The verification OTP code input to verify.

Request Parameters (Body)

Field Type Required Description
reference string No A unique reference ID to match requests and responses.

Response Fields

Field Format Description
reference string The unique reference submitted in the request, if any.
responseCode integer Status code from the API. 0 indicating success.
responseMessage string Description message corresponding to the response code.
curl -X POST "https://api.geniq.io/rest/v1/verify/otp_session_id?code=123456" \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -d "reference=12345"
const axios = require('axios');
const qs = require('qs');

axios.post('https://api.geniq.io/rest/v1/verify/otp_session_id?code=123456', qs.stringify({
  reference: '12345'
}), {
  headers: { 
    'Authorization': 'Bearer YOUR_TOKEN',
    'Content-Type': 'application/x-www-form-urlencoded'
  }
})
.then(res => console.log(res.data));
import requests
url = 'https://api.geniq.io/rest/v1/verify/otp_session_id?code=123456'
payload = {
    'reference': '12345'
}
headers = {
    'Authorization': 'Bearer YOUR_TOKEN',
    'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.post(url, data=payload, headers=headers)
print(response.json())
package main
import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
)
func main() {
	data := url.Values{}
	data.Set("reference", "12345")

	req, _ := http.NewRequest(
		"POST",
		"https://api.geniq.io/rest/v1/verify/otp_session_id?code=123456",
		strings.NewReader(data.Encode()),
	)
	req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
JSON Response (200 OK)
{
  "reference": "12345",
  "responseMessage": "Success",
  "responseCode": "0"
}
POST /whatsapp/messages

Send WhatsApp Message

Deliver interactive, rich media, and template-based WhatsApp messages. Select a message type below to see its description, parameter table, and cURL payload example.

Note: Every WhatsApp message request requires recipient (country code + phone number without +) and type.

Manage WhatsApp Templates

Create, retrieve, or delete pre-approved message templates. WhatsApp requires templates for business-initiated communication outside of active 24-hour conversation sessions.

Create Template

POST /whatsapp/message_templates

Submit a new template design for pre-approval. Authentication categories must be configured properly.

FieldTypeRequiredDescription
namestringYesUnique identifier name (e.g. "auth_sample").
languagestringYesSupported language code (e.g. "en").
categorystringYes"MARKETING", "UTILITY", or "AUTHENTICATION".
headerstringNoHeader text context. Supports 1 variable placeholder (e.g., "Hi {{1}}").
headerFormatstringNoCurrently supports "text".
headerExamplearrayNoString examples matching the header variables.
bodystringYesMain template text content. Supports variables like {{1}}, {{2}}.
bodyExamplearrayNoString examples matching the body variables.
footerstringNoFooter signature text. Static content only (no variables).
otpAddSecurityRecommendationbooleanNoFor Authentication: Appends Meta security advice. Default: false.
otpMessageTtlstringNoFor Authentication: TTL in minutes (between 30s and 90m).
otpExpiredAfterstringNoFor Authentication: TTL display context in minutes.
otpCopyButtonTextstringNoFor Authentication: Label for copy button (max 25 chars).

Retrieve Templates

GET /whatsapp/message_templates

Get a list of templates filtered by limit, status, category, or language.

Query ParamTypeRequiredDescription
limitintegerNoResult count limit per page.
categorystringNoFilter by "UTILITY", "AUTHENTICATION", "MARKETING".
statusstringNoFilter by "APPROVED", "PENDING", "REJECTED", "DISABLED", etc.
namestringNoExact name match filter.
languagestringNoLanguage code filter.

Delete Template

DELETE /whatsapp/message_templates

Delete a pre-existing template. Deletions are irreversible.

Query ParamTypeRequiredDescription
namestringYesThe template name identifier to delete.
idstringNoThe direct template ID.
curl -X POST https://api.geniq.io/rest/v1/whatsapp/message_templates \
  -H 'Authorization: Bearer [TOKEN]' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "sample_template",
    "language": "en",
    "category": "MARKETING",
    "header": "Welcome {{1}}",
    "headerFormat": "text",
    "headerExample": ["User"],
    "body": "Nice to meet you. Welcome to GENIQ {{1}}!",
    "bodyExample": ["Ali"],
    "footer": "Thanks"
  }'
curl -X GET "https://api.geniq.io/rest/v1/whatsapp/message_templates\
?limit=5&category=MARKETING" \
  -H 'Authorization: Bearer [TOKEN]'
curl -X DELETE "https://api.geniq.io/rest/v1/whatsapp/message_templates\
?name=sample_template" \
  -H 'Authorization: Bearer [TOKEN]'
POST /voice

Text-to-Speech Callout

Convert written text into automated voice calls. The Voice API rings the recipient and speaks the message in the language/locale of choice.

FieldTypeRequiredDescription
recipientstringYesRecipient's mobile number (e.g. "6591234567").
messagestringYesText context to convert into voice speech.
localestringYesVoice language engine locale code (e.g., "en-US").
originatorstringYesThe Caller ID to display (default: "6531596518").
referencestringNoCustom tracking reference ID.
curl -X POST https://api.geniq.io/rest/v1/voice \
  -H 'Authorization: Bearer [TOKEN]' \
  -H 'Content-Type: application/json' \
  -d '{
    "recipient": "6591234567",
    "message": "Hi, this is a test text-to-speech callout from GENIQ. Your verification code is 5 5 2 1.",
    "locale": "en-US",
    "originator": "6531596518",
    "reference": "call_123"
  }'
const axios = require('axios');
axios.post('https://api.geniq.io/rest/v1/voice', {
  recipient: "6591234567",
  message: "Hi, this is a test text-to-speech callout from GENIQ. Your verification code is 5 5 2 1.",
  locale: "en-US",
  originator: "6531596518",
  reference: "call_123"
}, {
  headers: { 'Authorization': 'Bearer [TOKEN]' }
}).then(res => console.log(res.data));
import requests
headers = { 'Authorization': 'Bearer [TOKEN]' }
data = {
    "recipient": "6591234567",
    "message": "Hi, this is a test text-to-speech callout from GENIQ. Your verification code is 5 5 2 1.",
    "locale": "en-US",
    "originator": "6531596518",
    "reference": "call_123"
}
response = requests.post('https://api.geniq.io/rest/v1/voice', json=data, headers=headers)
print(response.json())
package main
import (
	"bytes"
	"encoding/json"
	"net/http"
)
func main() {
	payload := map[string]interface{}{
		"recipient": "6591234567",
		"message": "Hi, this is a test text-to-speech callout from GENIQ. Your verification code is 5 5 2 1.",
		"locale": "en-US",
		"originator": "6531596518",
		"reference": "call_123",
	}
	body, _ := json.Marshal(payload)
	req, _ := http.NewRequest("POST", "https://api.geniq.io/rest/v1/voice", bytes.NewBuffer(body))
	req.Header.Set("Authorization", "Bearer [TOKEN]")
	req.Header.Set("Content-Type", "application/json")
	http.DefaultClient.Do(req)
}
POST /voice

Custom IVR Callout

Create dynamic, multi-tier interactive voice response (IVR) phone surveys or routing lines using nested DTMF menus.

FieldTypeRequiredDescription
recipientstringYesRecipient's mobile number.
originatorstringYesCaller ID display number.
localestringYesTTS voice engine locale.
maxDurationintegerNoMaximum call duration in seconds.
bargebooleanNoAllow DTMF buttons to interrupt/skip active spoken message. Default: false.
menusarrayYesNested list of menu objects.
menus[].menuIdstringYesUnique identifier name for this menu node.
menus[].messagestringYesThe spoken prompt message for this menu.
menus[].optionsarrayYesDigit options array. See below.
options[].dtmfstringYesDigit key pressed (e.g. "1", "2").
options[].actionstringYes"return" (ends call and records DTMF value) or "menus" (navigates).
options[].returnValuestringNoValue to return on "return" action (single word).
options[].targetMenustringNoTarget menu identifier if action is "menus".
curl -X POST https://api.geniq.io/rest/v1/voice \
  -H 'Authorization: Bearer [TOKEN]' \
  -H 'Content-Type: application/json' \
  -d '{
    "recipient": "6591234567",
    "originator": "6531596518",
    "reference": "survey_1",
    "maxDuration": 30,
    "barge": true,
    "locale": "en-US",
    "menus": [
      {
        "menuId": "main",
        "message": "Press 1 for Support, or press 2 to speak to Sales.",
        "options": [
          { "dtmf": "1", "action": "return", "returnValue": "Support" },
          { "dtmf": "2", "action": "return", "returnValue": "Sales" }
        ]
      }
    ]
  }'
curl -X POST https://api.geniq.io/rest/v1/voice \
  -H 'Authorization: Bearer [TOKEN]' \
  -H 'Content-Type: application/json' \
  -d '{
    "recipient": "6591234567",
    "originator": "6531596518",
    "reference": "nest_1",
    "maxDuration": 45,
    "barge": true,
    "locale": "en-US",
    "menus": [
      {
        "menuId": "main",
        "message": "Press 1 for Billing, or press 2 for general support menu.",
        "options": [
          { "dtmf": "1", "action": "return", "returnValue": "Billing" },
          { "dtmf": "2", "action": "menus", "targetMenu": "sub_support" }
        ]
      },
      {
        "menuId": "sub_support",
        "message": "Press 1 for technical help, or press 2 to return to main menu.",
        "options": [
          { "dtmf": "1", "action": "return", "returnValue": "TechHelp" },
          { "dtmf": "2", "action": "menus", "targetMenu": "main" }
        ]
      }
    ]
  }'

Supported Voice Locales

Below is the listing of supported voices, languages, and locale identifiers for text-to-speech calls.

LanguageLocale Code
English (US)en-US
English (British)en-GB
English (Australian)en-AU
English (Indian)en-IN
Chinese Mandarincmn-CN
Chinese Cantonesezh-HK
Malay (Malaysia)ms-MY
Indonesianid-ID
Arabicarb
Spanishes-ES
Spanish (US)es-US
Portuguese (European)pt-PT
Portuguese (Brazilian)pt-BR
Frenchfr-FR
French (Canadian)fr-CA
Germande-DE
Italianit-IT
Japaneseja-JP
Koreanko-KR
Turkishtr-TR
Russianru-RU
Polishpl-PL
Thaith-TH
Vietnamesevi-VN
Locale Settings Example
// Set the "locale" variable inside voice JSON
{
  "recipient": "6591234567",
  "message": "Welcome to GENIQ Technologies",
  "locale": "en-US" // or cmn-CN, ms-MY, etc.
}

Receiving SMS Callback

Incoming SMS messages sent to your virtual numbers are forwarded to your configured webhook URL via an HTTP POST request. The application server should return a status code of 200 OK; otherwise, the gateway will retry transmission.

Field Type Description
messageId string A unique ID associated with this received SMS message.
recipient integer The recipient of this SMS message (your virtual number/short code).
originator integer The sender of this message (mobile handset number).
udh string User Data Header. Only present if the incoming message is concatenated.
message string The body content of the incoming SMS message.
messageTimestamp string The creation date and time of the message in RFC3339 format (Y-m-d\TH:i:sP).
Sample Callback Request (POST / URL Encoded)
POST /your_webhook_endpoint HTTP/1.1
Host: your_domain.com
Content-Type: application/x-www-form-urlencoded

messageId=msg123\
&recipient=88888\
&originator=6591234567\
&message=hello\
&messageTimestamp=2017-01-03T14%3A31%3A28%2B08%3A00

SMS Delivery Reports

Real-time SMS delivery status updates are forwarded to your configured callback webhook via HTTP POST. If your server is offline or fails to respond with a 200 OK status, the gateway will queue the DLR for retry.

Field Type Description
messageId string The unique ID that was previously returned by our API when sending out the SMS.
channel string The channel type. For SMS, this value will always be set to "sms".
recipient integer The recipient's mobile number.
status string The status of the message sent. Possible values: processed, delivered, expired, deleted, undeliverable, rejected, unknown.
reasonCode integer Additional error description code if transmission fails. Refer to the Reason Codes reference table.
messageTimestamp string The creation date and time of this report on GENIQ in RFC3339 format.
operatorTimestamp string The creation date and time of this report on the operator SMSC in RFC3339 format.
Sample DLR Webhook Payload
POST /your_webhook_endpoint HTTP/1.1
Host: your_domain.com
Content-Type: application/x-www-form-urlencoded

messageId=msg123\
&channel=sms\
&recipient=6591234567\
&status=delivered\
&reasonCode=0\
&messageTimestamp=2017-01-03T14%3A31%3A28%2B08%3A00\
&operatorTimestamp=2017-01-03T14%3A31%3A00%2B08%3A00

Receiving WhatsApp Callback

Incoming WhatsApp messages will be delivered to a pre-configured callback URL using the HTTP POST method with a JSON body payload.

FieldTypeDescription
messageIdstringA unique ID associated with this WhatsApp message.
typestringMessage type. Possible values: text, image, video, audio, document, location, sticker, contact.
recipientintegerThe business number receiving the message.
originatorintegerThe sender's mobile number.
originatorNamestringThe sender's profile display name.
bodystringMessage body text. Only present for type "text".
urlstringPublicly accessible URL of the media file (image, video, audio, sticker, document).
messageTimestampstringThe message creation timestamp in RFC3339 format (Y-m-d\TH:i:sP).
Sample Callback: Text & Image JSON
{
  "messageId": "a662179e-ba00-492f-a0b7-06b3fa002502",
  "type": "text",
  "originator": "6588880000",
  "originatorName": "Mark Gold",
  "recipient": "6598989898",
  "body": "Hi, this is a test message",
  "messageTimestamp": "2025-02-20T14:45:42+08:00"
}
{
  "messageId": "45fd72c3-3495-4313-ba5d-be2d0acff3ca",
  "type": "image",
  "originator": "6588880000",
  "originatorName": "Mark Gold",
  "recipient": "6598989898",
  "url": "https://geniq.io/media/callback.jpg",
  "messageTimestamp": "2025-02-20T14:57:43+08:00"
}

WhatsApp Delivery Reports

Delivery status updates for sent WhatsApp messages are forwarded to your webhook URL via HTTP POST JSON payloads.

FieldTypeDescription
messageIdstringThe unique message ID returned by the API during submission.
channelstringWill always be set to "whatsapp".
recipientintegerThe mobile number of the recipient.
statusstringStatus: processed, sent, delivered, read, failed, expired, exceeded_retry.
reasonCodeintegerStandardized reason failure code. 0 indicating success.
messageTimestampstringGENIQ platform event creation timestamp (RFC3339).
providerTimestampstringMeta platform event creation timestamp (RFC3339).

đź’ˇ Webhook Response
Your server should always respond with HTTP Status Code 200 (OK). Any other status will trigger automatic delivery retries.

Sample Callback: Delivery Report JSON
{
  "messageId": "0c5b63cf-b41e-449c-a077-9124de0b87dc",
  "recipient": "6588880000",
  "status": "delivered",
  "reasonCode": "0",
  "channel": "whatsapp",
  "messageTimestamp": "2025-02-20T15:23:56+08:00",
  "providerTimestamp": "2025-02-20T15:23:55+08:00"
}

SMPP Protocol Reference

GENIQ operates a high-throughput, low-latency Short Message Peer-to-Peer (SMPP) gateway for customers needing native telecommunication interfaces. Our gateway fully supports the SMPP v3.4 standard exclusively.

Contact our integration sales team to request SMPP system credentials and whitelist client IP ranges.

Connection Parameters

Parameter Value / Description
Host smpp.geniq.io
Port 2775
system_id Your assigned client system ID.
password Your assigned client password credentials.
system_type Ignored.

Binds & Throughput

Property Default Limit
Binds per system_id 2 (transceiver, transmitter, or receiver binds)
Maximum Throughput 10 messages per second (can be raised upon request)

Supported PDUs

PDU Name Command ID Type
bind_receiver / bind_receiver_resp 0x00000001 / 0x80000001 Session management
bind_transmitter / bind_transmitter_resp 0x00000002 / 0x80000002 Session management
bind_transceiver / bind_transceiver_resp 0x00000009 / 0x80000009 Session management
submit_sm / submit_sm_resp 0x00000004 / 0x80000004 Message submission
deliver_sm / deliver_sm_resp 0x00000005 / 0x80000005 Delivery report / Mobile terminated receive
unbind / unbind_resp 0x00000006 / 0x80000006 Session termination
enquire_link / enquire_link_resp 0x00000015 / 0x80000015 Keep-alive signal
generic_nack 0x80000000 Negative response packet

Supported Data Codings

Value Encoding / Alphabet Scheme
0 GSM7 default alphabet
1 GSM7 default alphabet
2 8-Bit binary encoding data
8 UTF-16BE (UCS2) double-byte alphabet

Concatenated SMS TLVs

Tag Name Hex Value Description
sar_msg_ref_num 0x020C Concatenation message reference number index.
sar_total_segments 0x020E Total parts number count in multipart text.
sar_segment_seqnum 0x020F The current part index segment sequence number.
SMPP Bind Details
// SMPP v3.4 binds can be initiated via TCP socket to smpp.geniq.io:2775.
// IP authentication is required prior to binding.
// Ensure transmitter or transceiver bind requests contain system_id and password.
// Periodic enquire_link PDUs must be sent every 30 seconds to avoid connection drop.

API Response & Reason Codes

GENIQ maps all API requests to standard HTTP status codes, complemented by descriptive custom application codes in the JSON body payloads.

RESTful API Response Codes

Code Description / Meaning
0Success
1Invalid Username or Password
2Invalid IP request
3Account has expired
4Account is disabled
5Account maximum throttling rate is exceeded
6Account does not have sufficient credit balance
7Prepaid Account has expired
10Could not route message
11Invalid recipient address
12Invalid originating address
13Invalid alphanumeric originating address
14Could not route message due to account limitations
15Subscriber has blocked this service
16Destination Address Duplicated
17Destination Address list exceeded maximum
18API token generation failed
19Spam Control threshold exceeded
20Invalid Token
21Invalid messageId
22Invalid code
23Token expired
24Invalid API Key credentials
88General Failure
99System error. Please contact us if problem persists

SMS Delivery Reason Codes

Reason codes returned inside delivery reports when an SMS fails to transmit to the destination handset.

Code Description / Failure Cause
0Not Applicable / Success
1Base Station Unknown
2MSC Unknown
3Format Error
4Other Error
5Subscriber Unknown
6Subscriber Barred
7Subscriber Not Provisioned
8Subscriber Absent
9SMSC Failure
10SMSC Congestion
11SMSC Roaming
12Handset Error
13Handset Memory Exceeded
201Invalid WhatsApp Template

WhatsApp Channel Response Codes

Code Description / Meaning
301No valid WhatsApp session found
302WhatsApp Template not found
303WhatsApp Template param type 'otp' is required for the authentication template
304WhatsApp Template is not approved
305WhatsApp Template param count mismatch
306WhatsApp Template param type 'otp' is required for authentication template
311WhatsApp Template rejected
312WhatsApp Template with same content already existed
313WhatsApp Template is missing the name field
314WhatsApp Template is missing the language field
315WhatsApp Template is missing the category field
316WhatsApp Template is missing the body field
317WhatsApp Template is missing the header parameter example
318WhatsApp Template is missing the body parameter example
319WhatsApp Template has an invalid number of body parameter examples
320WhatsApp Template contains an invalid footer. Variables are not supported in the footer
321WhatsApp Template header format must be one of {TEXT, IMAGE}
322WhatsApp Template category must be one of {UTILITY, MARKETING, AUTHENTICATION}
323WhatsApp Template header field can only have up to 1 variable(s)
324WhatsApp Template header has an invalid variable sequence
325WhatsApp Template body has an invalid variable sequence
326WhatsApp Template OTP time to live value must be higher than or equal to 30
327WhatsApp Template OTP code expiry time should be between 1 and 90 minutes
328WhatsApp Template OTP copy button text can't have more than 25 characters
Error Envelope Payload
{
  "responseCode": "6",
  "responseMessage": "Account does not have sufficient credit balance"
}