Reliable messaging for real operations
SMS that fits the systems you already run.
Send transactional messages, reminders, alerts, and bulk campaigns through one signed REST endpoint. Build with JSON or upload prepared message files.
Signed requests
JSON and files
Delivery tracking
Prepare
Create JSON or a CSV message file.
Hash
SHA-256 the exact bytes being sent.
Sign
Create an HMAC signature with your secret.
Send
POST once and track the returned message ID.
Endpoint
One endpoint, two delivery modes
Send a signed POST request using either an exact JSON body or a multipart file upload. Use the API hostname issued for your environment.
POST https://sms.vomule.net/api/v1/send-smsTooling
Use OpenAPI or Postman
Download the OpenAPI spec for Swagger-compatible tools, or import the Postman collection for quick tests. The Postman JSON request signs itself after you set your collection variables.
For CSV uploads, Postman cannot hash the selected local file in a pre-request script. Use the PHP, JavaScript, or Python file-upload example to calculate the file body hash and signature, then paste those values into the collection variables.
Security
Sign every request on your server
Authentication combines your client ID, a current Unix timestamp, a SHA-256 body hash, and an HMAC-SHA256 signature.
| Header | Value |
|---|---|
X-Client-ID | Your issued client ID |
X-Timestamp | Current Unix timestamp in seconds; accepted for five minutes |
X-Body-Hash | SHA-256 of the exact JSON bytes or original uploaded file bytes |
X-Signature | Lowercase HMAC-SHA256 signature |
{timestamp}POST/api/v1/send-sms{bodyHash}HMAC_SHA256(signatureBase, clientSecret)Keep the client secret in server environment variables. Never place it in browser JavaScript, mobile applications, repositories, logs, or support messages.
Examples
Send one message
Hash the exact JSON bytes you send. These examples read credentials from environment variables and preserve the same encoded body for hashing and transmission.
<?php
$clientId = getenv('VOMULE_SMS_CLIENT_ID');
$clientSecret = getenv('VOMULE_SMS_CLIENT_SECRET');
$baseUrl = rtrim(getenv('VOMULE_SMS_BASE_URL'), '/');
$path = '/api/v1/send-sms';
$timestamp = time();
$payload = ['msisdn' => '+26650123456', 'message' => 'Hello from PHP', 'request_id' => 'order-1001'];
$rawBody = json_encode($payload, JSON_UNESCAPED_SLASHES);
$bodyHash = hash('sha256', $rawBody);
$signature = hash_hmac('sha256', $timestamp . 'POST' . $path . $bodyHash, $clientSecret);
$ch = curl_init($baseUrl . $path);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
"X-Client-ID: {$clientId}", "X-Timestamp: {$timestamp}",
"X-Body-Hash: {$bodyHash}", "X-Signature: {$signature}",
],
CURLOPT_POSTFIELDS => $rawBody,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);Request body
{
"msisdn": "+26650123456",
"message": "Your verification code is 482913.",
"request_id": "order-20260622-0001"
}Success response
{
"message": "Message successfully queued",
"status": "queued",
"message_id": "019..."
}Bulk mode
Upload a prepared message file
CSV rows use msisdn,message,request_id. For multipart mode, hash only the original file bytes, not the multipart envelope.
<?php
$clientId = getenv('VOMULE_SMS_CLIENT_ID');
$clientSecret = getenv('VOMULE_SMS_CLIENT_SECRET');
$baseUrl = rtrim(getenv('VOMULE_SMS_BASE_URL'), '/');
$path = '/api/v1/send-sms';
$filePath = '/path/to/messages.csv';
$timestamp = time();
$bodyHash = hash_file('sha256', $filePath);
$signature = hash_hmac('sha256', $timestamp . 'POST' . $path . $bodyHash, $clientSecret);
$ch = curl_init($baseUrl . $path);
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-Client-ID: {$clientId}", "X-Timestamp: {$timestamp}", "X-Body-Hash: {$bodyHash}", "X-Signature: {$signature}"],
CURLOPT_POSTFIELDS => ['file' => new CURLFile($filePath)],
]);
$response = curl_exec($ch);
curl_close($ch);Example CSV
+26650123456,"Your order is ready",order-1001
+26658123456,"Your appointment is tomorrow",appointment-2048Success response
{ "message": "File successfully uploaded" }Operations
Errors and safe retries
| Status | Meaning |
|---|---|
| 400 | The supplied body hash does not match the received bytes. |
| 401 | Credentials, timestamp, hash, or signature are invalid. |
| 422 | Message fields or the uploaded file failed validation. |
| 429 | The client exceeded its rate limit and should retry with backoff. |
| 500 | An unexpected service error occurred. |
Use a unique request_id for tracing. Check the response and delivery logs before retrying; repeated request IDs are not currently guaranteed to be idempotent.