Quick Start
Send your first SMS in under 5 minutes. All you need is your API key.
# Send an SMS via the SBS TELECOM REST API
curl -X POST https://api.sbstelecom.co.uk/v1/messages \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+447911123456",
"from": "SBSTEL",
"text": "Hello from SBS TELECOM!"
}'
# Response
{
"message_id": "msg_01HX4Y9Z3K2W8V6N5P7Q",
"status": "queued",
"to": "+447911123456",
"from": "SBSTEL",
"parts": 1,
"cost": 0.0042
}
<?php
$response = file_get_contents('https://api.sbstelecom.co.uk/v1/messages', false, stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Authorization: Bearer YOUR_API_KEY\r\nContent-Type: application/json",
'content' => json_encode([
'to' => '+447911123456',
'from' => 'SBSTEL',
'text' => 'Hello from SBS TELECOM!',
]),
],
]));
$result = json_decode($response, true);
echo 'Message ID: ' . $result['message_id'];
import requests
response = requests.post(
'https://api.sbstelecom.co.uk/v1/messages',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
json={
'to': '+447911123456',
'from': 'SBSTEL',
'text': 'Hello from SBS TELECOM!',
}
)
data = response.json()
print(f"Message ID: {data['message_id']}, Status: {data['status']}")
const response = await fetch('https://api.sbstelecom.co.uk/v1/messages', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
to: '+447911123456',
from: 'SBSTEL',
text: 'Hello from SBS TELECOM!',
}),
});
const { message_id, status } = await response.json();
console.log(`Sent: ${message_id} — ${status}`);
Developer Sandbox
Test your integration without affecting live traffic. The sandbox environment mirrors production with full DLR simulation.
Sandbox Endpoint
https://sandbox.api.sbstelecom.co.uk/v1
Identical to production. Outbound messages are swallowed — no real SMS sent.
SMPP Sandbox Host
smpp-sandbox.sbstelecom.co.uk:2775
Accepts binds and submit_sm PDUs. Returns simulated delivery receipts.
Simulated DLRs
DELIVRD / UNDELIV / REJECTD
Append ?dlr_sim=UNDELIV to test failure scenarios in your webhook handler.
Get Sandbox Credentials
Request free sandbox access — no credit card required. Full API parity with production.
Request AccessAuthentication
All API requests are authenticated using Bearer tokens passed in the HTTP Authorization header.
| Header | Value | Required |
|---|---|---|
Authorization | Bearer <API_KEY> | Required |
Content-Type | application/json | Required |
X-Request-ID | UUID v4 idempotency key | Optional |
X-Callback-URL | DLR webhook override per-request | Optional |
Send SMS
POST /v1/messages
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
to | string | Required | E.164 format recipient number (+447911123456) |
from | string | Required | Alphanumeric sender ID (max 11 chars) or number |
text | string | Required | Message content. Multi-part handled automatically |
type | string | Optional | text (default), unicode, binary, flash |
callback_url | string | Optional | DLR webhook URL. Overrides account-level setting |
validity | integer | Optional | Message validity in minutes (default: 1440) |
scheduled_at | string | Optional | ISO 8601 datetime for scheduled delivery |
route | string | Optional | standard, premium, otp. Defaults to account route |
Bulk Messaging
POST /v1/messages/bulk Up to 10,000 recipients per request.
curl -X POST https://api.sbstelecom.co.uk/v1/messages/bulk \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "SBSTEL",
"text": "Your account statement is ready. Login at https://portal.example.com",
"recipients": [
{ "to": "+447911123456" },
{ "to": "+447911654321" },
{ "to": "+447911999000", "text": "Personalised override for this number" }
],
"route": "premium",
"callback_url": "https://yourapp.com/dlr-webhook"
}'
# Response
{
"batch_id": "batch_01HX9A2B3C4D5E6F7G8H",
"total": 3,
"queued": 3,
"failed": 0,
"status_url": "https://api.sbstelecom.co.uk/v1/batches/batch_01HX9A2B3C4D5E6F7G8H"
}
$payload = [
'from' => 'SBSTEL',
'text' => 'Your statement is ready.',
'recipients' => [
['to' => '+447911123456'],
['to' => '+447911654321'],
],
'route' => 'premium',
'callback_url' => 'https://yourapp.com/dlr-webhook',
];
$ch = curl_init('https://api.sbstelecom.co.uk/v1/messages/bulk');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_KEY',
'Content-Type: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
echo 'Batch ID: ' . $result['batch_id'];
DLR Webhooks
SBS TELECOM posts real-time delivery receipts to your callback_url via HTTP POST. Respond with 200 OK to acknowledge.
# Incoming DLR webhook POST payload
{
"message_id": "msg_01HX4Y9Z3K2W8V6N5P7Q",
"batch_id": "batch_01HX9A2B3C4D5E6F7G8H",
"to": "+447911123456",
"from": "SBSTEL",
"status": "DELIVRD",
"err_code": 0,
"err_desc": "Message delivered",
"submitted_at": "2026-03-26T10:00:00Z",
"delivered_at": "2026-03-26T10:00:01Z",
"network": "EE UK",
"mcc": "234",
"mnc": "30"
}
| Status | Description |
|---|---|
DELIVRD | Message delivered to handset |
ACCEPTD | Accepted by carrier, delivery pending |
UNDELIV | Undeliverable — invalid number or network error |
REJECTD | Rejected by carrier — content or sender ID issue |
EXPIRED | Validity period elapsed before delivery |
UNKNOWN | No DLR received from downstream carrier |
X-SBS-Signature header (HMAC-SHA256) against your webhook secret to verify authenticity of all incoming DLR callbacks.Error Codes
| HTTP | Code | Description |
|---|---|---|
| 400 | INVALID_NUMBER | Recipient number is not valid E.164 format |
| 400 | INVALID_SENDER | Sender ID exceeds 11 chars or uses disallowed chars |
| 400 | TEXT_TOO_LONG | Message exceeds 1600 characters (10 SMS parts) |
| 401 | INVALID_API_KEY | API key missing, expired or revoked |
| 402 | INSUFFICIENT_CREDIT | Account balance below minimum threshold |
| 403 | COUNTRY_BLOCKED | Destination country not enabled on your account |
| 429 | RATE_LIMITED | Too many requests — back-off and retry with exponential delay |
| 503 | GATEWAY_UNAVAILABLE | Temporary upstream issue — retry after Retry-After seconds |
SMPP v3.4 Overview
SBS TELECOM operates a purpose-built SMPP infrastructure supporting both SMPP v3.3 and v3.4. Designed for high-throughput platforms — fintechs, enterprise aggregators and OTP-heavy applications.
High-Throughput Binds
Up to 10,000 TPS per transceiver bind. Multiple concurrent binds supported for horizontal scaling.
TLS Encryption
All SMPP connections support TLS 1.2/1.3 on port 2776. Plain-text on port 2775 for legacy clients.
TLV Support
Full optional parameter (TLV) support including receipted_message_id, message_state, network_error_code and custom tags.
Unicode & Long SMS
GSM7, UCS-2 (Unicode) and 8-bit binary. Automatic segmentation and reassembly using SAR TLVs or UDH.
Connection Parameters
| Parameter | Value | Notes |
|---|---|---|
| Host | smpp.sbstelecom.co.uk | Production endpoint |
| Port (plain) | 2775 | Standard SMPP — legacy clients only |
| Port (TLS) | 2776 | Recommended — TLS 1.2 / 1.3 |
| Protocol | SMPP v3.3 / v3.4 | v3.4 recommended |
| system_id | Provided on account creation | Used for bind authentication |
| password | Max 8 characters | Rotatable in client portal |
| system_type | SMS or leave blank | Account-specific value if required |
| enquire_link | Every 30 seconds | Required — idle connections terminated after 60s |
| Encoding | data_coding=0 (GSM7), 8 (UCS-2) | See encoding table |
Bind Types
bind_transmitter
MO only — outbound SMS submission. Use when you only need to send messages and handle DLRs via HTTP webhook rather than SMPP deliver_sm.
command_id: 0x00000002
bind_receiver
Inbound only — receive DLR callbacks and inbound SMS (MO) over the SMPP connection as deliver_sm PDUs.
command_id: 0x00000001
bind_transceiver Recommended
Bidirectional — send and receive on a single connection. Recommended for high-throughput deployments and OTP platforms requiring low-latency DLRs.
command_id: 0x00000009
TLV (Optional) Parameters
SBS TELECOM supports the full SMPP v3.4 optional parameter set. Key TLVs for enterprise integrations:
| Tag | Hex | Direction | Description |
|---|---|---|---|
receipted_message_id | 0x001E | DLR | Original message ID in delivery receipts. Use to correlate DLRs with submissions |
message_state | 0x0427 | DLR | Final delivery state: 1=ENROUTE, 2=DELIVERED, 3=EXPIRED, 5=UNDELIVERABLE, 6=ACCEPTED |
network_error_code | 0x0423 | DLR | 3-byte field: network type byte + 2-byte error code from carrier |
sar_msg_ref_num | 0x020C | Submit | Reference number for long message segmentation (SAR). Use with sar_total_segments / sar_segment_seqnum |
sar_total_segments | 0x020E | Submit | Total number of segments in a concatenated message |
sar_segment_seqnum | 0x020F | Submit | Sequence number of this segment (1-based) |
dest_addr_subunit | 0x0005 | Submit | Flash SMS: set to 0x01 for Class 0 (display-only) messages |
user_message_reference | 0x0204 | Submit | Your internal reference ID. Echoed back in DLR deliver_sm |
callback_num | 0x0381 | Submit | Reply-to number for MO responses |
TLV Example — DLR Parsing
# Python: Parse TLV fields from deliver_sm DLR
def parse_dlr_tlvs(pdu):
msg_id = pdu.get_tlv(0x001E) # receipted_message_id
state = pdu.get_tlv(0x0427) # message_state (1=delivered, 5=undeliverable)
err_code = pdu.get_tlv(0x0423) # network_error_code
if state == 2:
mark_delivered(msg_id)
elif state == 5:
net_type = err_code[0]
net_err = int.from_bytes(err_code[1:3], 'big')
mark_failed(msg_id, net_type, net_err)
DLR & Callbacks over SMPP
Request DLRs on submit_sm by setting registered_delivery. Receipts arrive as deliver_sm PDUs on your receiver or transceiver bind.
| registered_delivery | Behaviour |
|---|---|
0x00 | No DLR requested |
0x01 | DLR on final delivery or failure only |
0x02 | DLR on delivery failure only |
0x03 | DLR on delivery success only |
0x10 | Intermediate DLRs (enroute state updates) |
0x11 | All DLRs — success, failure and intermediate (recommended for OTP) |
# submit_sm field summary for OTP with full DLR
submit_sm:
source_addr: "SBSBANK"
dest_addr: "+447911123456"
short_message: "Your OTP is 482910. Valid for 5 minutes."
data_coding: 0 # GSM7
registered_delivery: 0x11 # All DLRs
validity_period: "000000000005000R" # 5 minute expiry
TLVs:
user_message_reference: "TXN-98765-OTP" # your internal ref
Throughput & Window Sizing
Window Size
Default window size is 10 outstanding PDUs. Enterprise accounts can request up to 100 PDUs per bind for maximum throughput.
Multiple Binds
Scale horizontally by opening multiple transceiver binds. Each bind runs independently — ideal for load-balanced microservices.
Throughput Limits
Standard accounts: 100 TPS. Enterprise: 10,000 TPS per bind. Contact sales for high-volume OTP or financial alerting requirements.
enquire_link PDU every 30 seconds on idle connections. Connections without activity for 60 seconds will be closed by the server. Implement automatic reconnect with exponential back-off.PHP — Send with DLR Webhook
<?php
/**
* SBS TELECOM — Send SMS with DLR webhook (PHP)
*/
function sbstelSendSMS(string $apiKey, array $params): array {
$ch = curl_init('https://api.sbstelecom.co.uk/v1/messages');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($params),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer {$apiKey}",
'Content-Type: application/json',
],
CURLOPT_TIMEOUT => 10,
]);
$body = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("SMS API error {$httpCode}: {$body}");
}
return json_decode($body, true);
}
// Usage
$result = sbstelSendSMS('YOUR_API_KEY', [
'to' => '+447911123456',
'from' => 'SBSTEL',
'text' => 'Your verification code is 482910',
'route' => 'otp',
'callback_url' => 'https://yourapp.com/dlr',
]);
echo "Sent: {$result['message_id']}";
// DLR webhook handler
$dlr = json_decode(file_get_contents('php://input'), true);
$sig = $_SERVER['HTTP_X_SBS_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', file_get_contents('php://input'), 'YOUR_WEBHOOK_SECRET');
if (!hash_equals($expected, $sig)) {
http_response_code(403); exit;
}
if ($dlr['status'] === 'DELIVRD') {
markDelivered($dlr['message_id']);
}
http_response_code(200);
Ready to Build?
Get your API credentials, explore the sandbox and integrate in minutes. Our engineering team is available for technical onboarding calls.