Verification on request
Help customers complete signup or confirm access with a code requested in your app.
TOGETHER SMS · SMS API in Egypt
Connect your app or store to an SMS API in Egypt. Turn business events into useful customer messages: a login code, an order confirmation, a reminder or a shipment update. Connect over HTTPS from your backend, with one balance for API and Bulk SMS.
THE IDEA, CLEARLY
A service message puts important information within easy reach. Your system chooses the recipient, content and timing, then calls the gateway to send. Your application remains responsible for OTP generation, expiry and attempt limits.
BUILT AROUND YOUR BUSINESS
Help customers complete signup or confirm access with a code requested in your app.
Send an order confirmation or the payment state already recorded in your system.
Share a shipment update when your system records a status change, with a clear next step.
Trigger visit reminders or subscription expiry notices from your application schedule.
FROM IDEA TO MESSAGE
Once an order is confirmed in your store, the backend requests a short SMS update. Include the order reference and next step, and keep passwords and payment details out of the message.
A CLEAR START
We review the documents and complete Sender Name approval before branded sending.
Your team stores credentials on the server and starts with a balance lookup.
Test on a number you own and review the response, units and observed delivery.
Connect the right events to messages; investigate unknown outcomes before resending.
KNOW THE COST
Activate your Sender Name once for Bulk SMS and the API, then choose your message balance. Sender activation and message usage are separate costs.
2,150 EGP
Excludes 14% VAT; total EGP 2,451.
Gift added after approval and activation under the offer, for API or Bulk SMS.
Use the same account balance through your API integration or the Bulk SMS dashboard. Minimum balance purchase: 1,000 units.
| Units | Price · EGP | Per unit |
|---|---|---|
| 1,000 | 270 | 0.270 |
| 5,000 | 1,350 | 0.270 |
| 10,000 | 2,650 | 0.265 |
| 20,000 | 5,200 | 0.260 |
| 50,000 | 12,750 | 0.255 |
| 100,000 | 25,000 | 0.250 |
| 150,000 | 36,750 | 0.245 |
Prices exclude 14% VAT. Each message part per recipient uses one unit; length and encoding can change unit usage.
BEFORE YOU START
Yes. A developer connects from your backend using an HTTP client. The guide includes cURL, PHP, Node.js, Python and C# examples. Use the Bulk SMS dashboard for campaigns without code.
Both use one account balance. The 1,000-SMS gift is added after Sender Name approval and activation under the offer.
Each message part per recipient consumes a unit. Check language and length before sending: up to 70 Arabic or 160 GSM-7 English characters for a single part; symbols and encoding can change the number of parts.
TOGETHER SMS
Share your application type, use case and estimated volume. We will review activation and a suitable package, and point your team to the integration guide.
START WITH A BALANCE CHECK
Complete onboarding and required business documents to obtain API credentials and an approved sender.
Store credentials securely on your server, then retrieve your account balance.
Use your own test device and approved sender; check acceptance, cost and observed delivery.
https://togethersms.com/sendsms.phpFor balance: send user, password and action=get. A valid response is numeric plain text and can contain decimals.
# Run on your server; load secrets from your environment.
curl --get 'https://togethersms.com/sendsms.php' \
--connect-timeout 10 --max-time 20 \
--data-urlencode "user=${TOGETHER_SMS_USER}" \
--data-urlencode "password=${TOGETHER_SMS_PASSWORD}" \
--data-urlencode 'action=get'
# Sending is a separate request. Use an approved test recipient.
# Add numbers, sender, message and lang; omit action=get.HTTP API REFERENCE
SMS sending uses HTTPS GET with query parameters. This table applies to sending; action=get is reserved for balance retrieval.
| Parameter | Required value |
|---|---|
user | API account username. |
password | API account password; store on your server. |
numbers | International digits, or a comma-separated list; no + or spaces. |
sender | Your approved, activated Sender ID. |
message | UTF-8 text; URL-encode every query value once. |
lang | en for English; ar for Arabic / Unicode. |
GET /sendsms.php?user=YOUR_USERNAME&password=YOUR_PASSWORD
&numbers=YOUR_AUTHORIZED_TEST_NUMBER
&sender=YOUR_APPROVED_SENDER
&message=Your%20order%20is%20ready&lang=en
Host: togethersms.comLine breaks are for readability; the real request is one URL. Encode values with your HTTP library and use an authorized test recipient.
| Plain-text body | Meaning and next step |
|---|---|
1 | Request accepted; not proof of handset delivery. |
1:201001234567 | Accepted with recipient list; validate the entire response. |
0 | General rejection. |
Invalid login | Check your account credentials securely. |
Missing or Empty Field | Check all required fields. |
Insufficient Balance | Check available balance and required units. |
Invalid Sender | Check the approved Sender ID. |
Sender name is not activated | Complete Sender ID activation. |
Invalid Message Language | Check lang and text encoding. |
BACKEND EXAMPLES
Balance examples load credentials from environment variables. This documentation page does not execute API requests.
# Run on your server; load secrets from your environment.
curl --get 'https://togethersms.com/sendsms.php' \
--connect-timeout 10 --max-time 20 \
--data-urlencode "user=${TOGETHER_SMS_USER}" \
--data-urlencode "password=${TOGETHER_SMS_PASSWORD}" \
--data-urlencode 'action=get'
# Sending is a separate request. Use an approved test recipient.
# Add numbers, sender, message and lang; omit action=get.// Backend only. Never expose provider credentials in a browser.
const query = new URLSearchParams({
user: process.env.TOGETHER_SMS_USER,
password: process.env.TOGETHER_SMS_PASSWORD,
action: 'get'
});
const response = await fetch(
'https://togethersms.com/sendsms.php?' + query,
{ redirect: 'error', signal: AbortSignal.timeout(20000) }
);
const body = (await response.text()).trim();
if (!response.ok || !/^[0-9]+(?:\.[0-9]+)?$/.test(body)) {
throw new Error('Balance request was not accepted');
}
// Keep decimal precision; do not log the request URL.<?php
// Backend only. Secrets come from your deployment environment.
$query = http_build_query(array(
'user' => getenv('TOGETHER_SMS_USER'),
'password' => getenv('TOGETHER_SMS_PASSWORD'),
'action' => 'get'
), '', '&', PHP_QUERY_RFC3986);
$ch = curl_init('https://togethersms.com/sendsms.php?' . $query);
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 20
));
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($body === false || $status < 200 || $status >= 300 ||
!preg_match('/\A[0-9]+(?:\.[0-9]+)?\z/', trim($body))) {
throw new RuntimeException('Balance request was not accepted');
}# Backend only. Requires the requests package.
import os
import re
import requests
response = requests.get(
'https://togethersms.com/sendsms.php',
params={
'user': os.environ['TOGETHER_SMS_USER'],
'password': os.environ['TOGETHER_SMS_PASSWORD'],
'action': 'get'
},
timeout=(10, 20),
allow_redirects=False
)
body = response.text.strip()
if not (200 <= response.status_code < 300 and
re.fullmatch(r'[0-9]+(?:\.[0-9]+)?', body)):
raise RuntimeError('Balance request was not accepted')
# Timeout values are connect/read timeouts, not a strict total deadline.// Backend only. Use a supported .NET runtime.
using var handler = new HttpClientHandler { AllowAutoRedirect = false };
using var client = new HttpClient(handler) {
Timeout = TimeSpan.FromSeconds(20)
};
string user = Environment.GetEnvironmentVariable("TOGETHER_SMS_USER")!;
string password = Environment.GetEnvironmentVariable("TOGETHER_SMS_PASSWORD")!;
string url = "https://togethersms.com/sendsms.php?user=" +
Uri.EscapeDataString(user) + "&password=" +
Uri.EscapeDataString(password) + "&action=get";
using var response = await client.GetAsync(url);
string body = (await response.Content.ReadAsStringAsync()).Trim();
if (!response.IsSuccessStatusCode ||
!System.Text.RegularExpressions.Regex.IsMatch(
body, @"\A[0-9]+(?:\.[0-9]+)?\z")) {
throw new InvalidOperationException("Balance request was not accepted");
}DEVELOPER DOCUMENTATION / ENGLISH
Request and response reference, integration examples, failure handling and endpoint migration guidance.
PDF · v1.2 · 06 Nov 2026No. Flutter and web clients call your backend; only your backend stores SMS credentials and calls the gateway.
It means gateway acceptance. This contract does not document handset delivery confirmation or a delivery-report endpoint.
Treat the outcome as unknown and investigate before resending. The gateway may already have accepted it; automatic retries can duplicate messages.
The supplied contract has no scheduling parameter. Your application can manage timing; dashboard features do not automatically imply corresponding API endpoints.
The contract supports comma-separated recipients. Confirm batch, URL-length and request-rate limits with our team before large campaigns.
No. The target migration date is 30 June 2027. Test the new endpoint and follow our migration notices before changing production.
LET'S CONNECT YOUR BUSINESS
Tell us your use case so we can review sender activation and onboarding requirements.