Build with the kwtSMS API

Everything You Need to Start Sending SMS Fast

A complete, production-ready messaging API built for developers who need reliable delivery in Kuwait and beyond.

Simple REST/JSON API

POST to a single endpoint. Get back structured JSON with message ID, credits charged, and balance. No XML, no SOAP, no complexity.

12 Official SDKs

Native client libraries for JavaScript, Python, PHP, Ruby, Go, Java, C#, Swift, Kotlin, Rust, Dart, and Zig. Get integrated in minutes.

All Kuwait Carriers Covered

Delivers to all four Kuwait carriers: Zain, Ooredoo, STC, and Virgin Mobile. Priority routing for transactional OTP sender IDs bypasses DND filters.

Number Validation

Validate batches of up to 200 numbers before sending. Returns OK, ER, and NR classifications to prevent wasting credits on bad numbers.

Delivery Tracking

Every send returns a unique message ID. Check queue status and international delivery reports via the /status/ and /dlr/ endpoints.

Transparent Pricing

Pay only for what you send. Each API response includes credits deducted and remaining balance, so you always know your spend without extra calls.


Start Sending in Minutes

One POST request is all it takes. Pick your language and copy the example below.

Direct API Call kwtsms_send.sh
curl -s -X POST 'https://www.kwtsms.com/API/send/' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{
    "username": "curl_your_api_user",
    "password": "curl_your_api_pass",
    "sender":   "YOUR-SENDER",
    "mobile":   "96598765432",
    "message":  "Your OTP for cURL App is: 123456",
    "test":     "1"
  }'
Direct API Call kwtsms_send.php
$data = [
    'username' => 'php_your_api_user',
    'password' => 'php_your_api_pass',
    'sender'   => 'YOUR-SENDER',
    'mobile'   => '96598765432',
    'message'  => 'Your OTP for PHP App is: 123456',
    'test'     => '1',
];
$ch = curl_init('https://www.kwtsms.com/API/send/');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode($data),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Accept: application/json',
    ],
]);
$resp = json_decode(curl_exec($ch), true);
curl_close($ch);
if ($resp['result'] === 'OK') {
    echo 'Sent! Msg ID: ' . $resp['msg-id'];
} else {
    echo 'Error: ' . $resp['code'];
}
Using PHP SDK SDK kwtsms_sdk.php
require 'vendor/autoload.php';
use KwtSMS\KwtSMS; // composer require kwtsms/kwtsms

$sms = new KwtSMS('php_your_api_user', 'php_your_api_pass', 'YOUR-SENDER');

$result = $sms->send('96598765432', 'Your OTP for PHP SDK App is: 123456');

if ($result['result'] === 'OK') {
    echo 'Sent! Msg ID: ' . $result['msg-id'];
} else {
    echo 'Error: ' . $result['code'];
}
Direct API Call kwtsms_send.py
import requests

payload = {
    "username": "py_your_api_user",
    "password": "py_your_api_pass",
    "sender":   "YOUR-SENDER",
    "mobile":   "96598765432",
    "message":  "Your OTP for Python App is: 123456",
    "test":     "1",
}
resp = requests.post(
    "https://www.kwtsms.com/API/send/",
    json=payload,
    headers={"Accept": "application/json"},
)
data = resp.json()
if data["result"] == "OK":
    print(f"Sent! Msg ID: {data['msg-id']}")
else:
    print(f"Error {data['code']}: {data['description']}")
Using Python SDK SDK kwtsms_sdk.py
from kwtsms import KwtSMS  # pip install kwtsms

sms = KwtSMS("py_your_api_user", "py_your_api_pass", "YOUR-SENDER")

result = sms.send("96598765432", "Your OTP for Python SDK App is: 123456")

if result["result"] == "OK":
    print(f"Sent! Msg ID: {result['msg-id']}")
else:
    print(f"Error {result['code']}: {result['description']}")
Direct API Call kwtsms_send.js
const resp = await fetch('https://www.kwtsms.com/API/send/', {
  method:  'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept':       'application/json',
  },
  body: JSON.stringify({
    username: 'js_your_api_user',
    password: 'js_your_api_pass',
    sender:   'YOUR-SENDER',
    mobile:   '96598765432',
    message:  'Your OTP for JavaScript App is: 123456',
    test:     '1',
  }),
});

const data = await resp.json();
if (data.result === 'OK') {
  console.log('Sent! Msg ID:', data['msg-id']);
} else {
  console.error('Error:', data.code, data.description);
}
Using JavaScript SDK SDK kwtsms_sdk.js
import { KwtSMS } from 'kwtsms'; // npm install kwtsms

const sms = new KwtSMS('js_your_api_user', 'js_your_api_pass', { senderId: 'YOUR-SENDER' });

const result = await sms.send('96598765432', 'Your OTP for JavaScript SDK App is: 123456');

if (result.result === 'OK') {
  console.log('Sent! Msg ID:', result['msg-id']);
} else {
  console.error('Error:', result.code, result.description);
}
Direct API Call kwtsms_send.rb
require 'net/http'
require 'json'

uri = URI('https://www.kwtsms.com/API/send/')
req = Net::HTTP::Post.new(uri,
  'Content-Type' => 'application/json',
  'Accept'       => 'application/json')
req.body = JSON.generate(
  username: 'ruby_your_api_user',
  password: 'ruby_your_api_pass',
  sender:   'YOUR-SENDER',
  mobile:   '96598765432',
  message:  'Your OTP for Ruby App is: 123456',
  test:     '1')

res  = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
data = JSON.parse(res.body)
if data['result'] == 'OK'
  puts "Sent! Msg ID: #{data['msg-id']}"
else
  puts "Error: #{data['code']}"
end
Using Ruby SDK SDK kwtsms_sdk.rb
require 'kwtsms'  # gem install kwtsms

sms = KwtSMS::Client.new('ruby_your_api_user', 'ruby_your_api_pass', sender_id: 'YOUR-SENDER')

result = sms.send_sms('96598765432', 'Your OTP for Ruby SDK App is: 123456')

if result['result'] == 'OK'
  puts "Sent! Msg ID: #{result['msg-id']}"
else
  puts "Error: #{result['code']}"
end
Direct API Call kwtsms_send.go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)

func main() {
    payload := map[string]string{
        "username": "go_your_api_user",
        "password": "go_your_api_pass",
        "sender":   "YOUR-SENDER",
        "mobile":   "96598765432",
        "message":  "Your OTP for Go App is: 123456",
        "test":     "1",
    }
    body, _ := json.Marshal(payload)
    req, _ := http.NewRequest("POST",
        "https://www.kwtsms.com/API/send/", bytes.NewBuffer(body))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Accept", "application/json")
    resp, _ := (&http.Client{}).Do(req)
    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    fmt.Println("Sent! Msg ID:", result["msg-id"])
}
Using Go SDK SDK kwtsms_sdk.go
package main

import (
    "fmt"
    "log"

    kwtsms "github.com/boxlinknet/kwtsms-go"
)

func main() {
    sms, err := kwtsms.New("go_your_api_user", "go_your_api_pass",
        kwtsms.WithSenderID("YOUR-SENDER"))
    if err != nil {
        log.Fatal(err)
    }

    result, err := sms.Send("96598765432", "Your OTP for Go SDK App is: 123456", "")
    if err != nil {
        log.Fatal(err)
    }
    if result.Result == "OK" {
        fmt.Println("Sent! Msg ID:", result.MsgID)
    } else {
        fmt.Println("Error:", result.Code, result.Description)
    }
}
Direct API Call KwtsmsSend.java
import java.net.URI;
import java.net.http.*;

public class SendSMS {
    public static void main(String[] args) throws Exception {
        var body = """
            {
              "username": "java_your_api_user",
              "password": "java_your_api_pass",
              "sender":   "YOUR-SENDER",
              "mobile":   "96598765432",
              "message":  "Your OTP for Java App is: 123456",
              "test":     "1"
            }""";
        var req = HttpRequest.newBuilder()
            .uri(URI.create("https://www.kwtsms.com/API/send/"))
            .header("Content-Type", "application/json")
            .header("Accept", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        var resp = HttpClient.newHttpClient()
            .send(req, HttpResponse.BodyHandlers.ofString());
        System.out.println(resp.body());
    }
}
Using Java SDK SDK KwtsmsSdk.java
// build.gradle: implementation 'com.github.boxlinknet:kwtsms-java:0.4.0'
import com.kwtsms.KwtSMS;
import com.kwtsms.SendResult;

public class SendSMS {
    public static void main(String[] args) {
        KwtSMS sms = new KwtSMS("java_your_api_user", "java_your_api_pass", "YOUR-SENDER");

        SendResult result = sms.send("96598765432", "Your OTP for Java SDK App is: 123456");

        if ("OK".equals(result.getResult())) {
            System.out.println("Sent! Msg ID: " + result.getMsgId());
        } else {
            System.out.println("Error: " + result.getCode() + " " + result.getDescription());
        }
    }
}
Direct API Call KwtsmsSend.cs
using System.Net.Http;
using System.Text;
using System.Text.Json;

var payload = new {
    username = "csharp_your_api_user",
    password = "csharp_your_api_pass",
    sender   = "YOUR-SENDER",
    mobile   = "96598765432",
    message  = "Your OTP for C# App is: 123456",
    test     = "1"
};

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
var content = new StringContent(
    JsonSerializer.Serialize(payload),
    Encoding.UTF8, "application/json");
var resp = await client.PostAsync(
    "https://www.kwtsms.com/API/send/", content);
var raw = await resp.Content.ReadAsStringAsync();
Console.WriteLine(raw);
Using C# SDK SDK KwtsmsSdk.cs
using KwtSMS; // dotnet add package KwtSMS

var sms = new KwtSmsClient("csharp_your_api_user", "csharp_your_api_pass", "YOUR-SENDER");

var result = sms.Send("96598765432", "Your OTP for C# SDK App is: 123456");

if (result.Result == "OK") {
    Console.WriteLine($"Sent! Msg ID: {result.MsgId}");
} else {
    Console.WriteLine($"Error: {result.Code} - {result.Description}");
}
Direct API Call kwtsms_send.rs
use reqwest;
use serde_json::json;

// Cargo.toml: reqwest = { version = "0.11", features = ["json"] }
// serde_json = "1"

#[tokio::main]
async fn main() {
    let payload = json!({
        "username": "rust_your_api_user",
        "password": "rust_your_api_pass",
        "sender":   "YOUR-SENDER",
        "mobile":   "96598765432",
        "message":  "Your OTP for Rust App is: 123456",
        "test":     "1"
    });
    let resp = reqwest::Client::new()
        .post("https://www.kwtsms.com/API/send/")
        .header("Accept", "application/json")
        .json(&payload)
        .send().await.unwrap();
    let data: serde_json::Value = resp.json().await.unwrap();
    println!("Sent! Msg ID: {}", data["msg-id"]);
}
Using Rust SDK SDK kwtsms_sdk.rs
use kwtsms::KwtSms; // cargo add kwtsms

fn main() {
    let sms = KwtSms::new("rust_your_api_user", "rust_your_api_pass",
        Some("YOUR-SENDER"), false, None).unwrap();

    let result = sms.send_one("96598765432", "Your OTP for Rust SDK App is: 123456", None).unwrap();

    if result["result"] == "OK" {
        println!("Sent! Msg ID: {}", result["msg-id"].as_str().unwrap_or(""));
    } else {
        println!("Error: {}", result["code"]);
    }
}
Direct API Call KwtsmsSend.kt
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import org.json.JSONObject

fun main() {
    val payload = JSONObject()
        .put("username", "kotlin_your_api_user")
        .put("password", "kotlin_your_api_pass")
        .put("sender",   "YOUR-SENDER")
        .put("mobile",   "96598765432")
        .put("message",  "Your OTP for Kotlin App is: 123456")
        .put("test",     "1")
    val body = RequestBody.create(
        "application/json".toMediaType(), payload.toString())
    val req = Request.Builder()
        .url("https://www.kwtsms.com/API/send/")
        .addHeader("Accept", "application/json")
        .post(body).build()
    val resp = OkHttpClient().newCall(req).execute()
    println(resp.body?.string())
}
Using Kotlin SDK SDK KwtsmsSdk.kt
// build.gradle.kts: implementation("com.github.boxlinknet:kwtsms-kotlin:0.1.4")
import com.kwtsms.KwtSMS

fun main() {
    val sms = KwtSMS("kotlin_your_api_user", "kotlin_your_api_pass", senderId = "YOUR-SENDER")

    val result = sms.send("96598765432", "Your OTP for Kotlin SDK App is: 123456")

    if (result.result == "OK") {
        println("Sent! Msg ID: ${result.msgId}")
    } else {
        println("Error: ${result.code}")
    }
}
Direct API Call KwtsmsSend.swift
import Foundation

let payload: [String: Any] = [
    "username": "swift_your_api_user",
    "password": "swift_your_api_pass",
    "sender":   "YOUR-SENDER",
    "mobile":   "96598765432",
    "message":  "Your OTP for Swift App is: 123456",
    "test":     "1"
]

var request = URLRequest(url: URL(string: "https://www.kwtsms.com/API/send/")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.httpBody = try! JSONSerialization.data(withJSONObject: payload)

URLSession.shared.dataTask(with: request) { data, _, _ in
    if let data = data,
       let str = String(data: data, encoding: .utf8) {
        print(str)
    }
}.resume()
Using Swift SDK SDK KwtsmsSdk.swift
// .package(url: "https://github.com/boxlinknet/kwtsms-swift.git", from: "0.2.0")
import KwtSMS

let sms = KwtSMS(username: "swift_your_api_user", password: "swift_your_api_pass", senderId: "YOUR-SENDER")

let result = await sms.send(mobile: "96598765432", message: "Your OTP for Swift SDK App is: 123456")

if result.result == "OK" {
    print("Sent! Msg ID: \(result.msgId ?? "")")
} else {
    print("Error: \(result.code ?? "") \(result.description ?? "")")
}
Direct API Call kwtsms_send.dart
import 'dart:convert';
import 'package:http/http.dart' as http;

// pubspec.yaml: http: ^1.2.0

void main() async {
  final resp = await http.post(
    Uri.parse('https://www.kwtsms.com/API/send/'),
    headers: {
      'Content-Type': 'application/json',
      'Accept':       'application/json',
    },
    body: jsonEncode({
      'username': 'dart_your_api_user',
      'password': 'dart_your_api_pass',
      'sender':   'YOUR-SENDER',
      'mobile':   '96598765432',
      'message':  'Your OTP for Dart App is: 123456',
      'test':     '1',
    }),
  );
  print(resp.body);
}
Using Dart SDK SDK kwtsms_sdk.dart
import 'package:kwtsms/kwtsms.dart'; // dart pub add kwtsms

void main() async {
  final sms = KwtSMS('dart_your_api_user', 'dart_your_api_pass', senderId: 'YOUR-SENDER');

  final result = await sms.send('96598765432', 'Your OTP for Dart SDK App is: 123456');

  if (result.result == 'OK') {
    print('Sent! Msg ID: ${result.msgId}');
  } else {
    print('Error: ${result.code}');
  }
}
Direct API Call kwtsms_send.zig
const std = @import("std");

// zig version 0.13+

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const alloc = gpa.allocator();

    var client = std.http.Client{ .allocator = alloc };
    defer client.deinit();

    const body =
        \\{"username":"zig_your_api_user","password":"zig_your_api_pass",
        \\ "sender":"YOUR-SENDER","mobile":"96598765432",
        \\ "message":"Your OTP for Zig App is: 123456","test":"1"}
    ;

    var resp = std.ArrayList(u8).init(alloc);
    defer resp.deinit();

    _ = try client.fetch(.{
        .method  = .POST,
        .location = .{ .url = "https://www.kwtsms.com/API/send/" },
        .extra_headers = &.{
            .{ .name = "Content-Type", .value = "application/json" },
            .{ .name = "Accept",       .value = "application/json" },
        },
        .payload = body,
        .response_storage = .{ .dynamic = &resp },
    });
    std.debug.print("{s}\n", .{resp.items});
}
Using Zig SDK SDK kwtsms_sdk.zig
// build.zig.zon: add kwtsms dependency, run `zig fetch --save`
const std = @import("std");
const kwtsms = @import("kwtsms");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    var sms = kwtsms.KwtSMS.init(
        allocator, "zig_your_api_user", "zig_your_api_pass", "YOUR-SENDER", false, null
    );

    const resp = try sms.sendOne("96598765432", "Your OTP for Zig SDK App is: 123456", null);

    if (resp.isOk()) {
        std.debug.print("Sent! Msg ID: {s}\n", .{ resp.msg_id.? });
    } else {
        std.debug.print("Error: {s}\n", .{ resp.code.? });
    }
}
Direct API Call kwtsms_send.pl
use LWP::UserAgent;
use JSON;

# cpanm LWP::Protocol::https JSON

my $ua   = LWP::UserAgent->new;
my $resp = $ua->post(
    'https://www.kwtsms.com/API/send/',
    'Content-Type' => 'application/json',
    'Accept'       => 'application/json',
    'Content'      => encode_json({
        username => 'perl_your_api_user',
        password => 'perl_your_api_pass',
        sender   => 'YOUR-SENDER',
        mobile   => '96598765432',
        message  => 'Your OTP for Perl App is: 123456',
        test     => '1',
    }),
);

my $data = decode_json($resp->content);
print "Sent! Msg ID: $data->{'msg-id'}\n";
Response
{
  "result":          "OK",
  "msg-id":          "f4c841adee210f31307633ceaebff2ec",
  "numbers":         1,
  "points-charged":  1,
  "balance-after":   180,
  "unix-timestamp":  1684763355
}
  • msg-id: Save this to check delivery status later via /status/
  • balance-after: Your credit balance after this send, no extra /balance/ call needed
  • numbers: Count of accepted and dispatched numbers in this batch
  • On error: code and description fields are returned instead
Set "test":"1" during development to queue messages without delivering or consuming credits. Switch to "test":"0" before going live.

How It Works

From API call to delivered message in seconds.

1
Your Application

POST a JSON payload with credentials, sender ID, recipient numbers, and message text to the kwtSMS API.

2
kwtSMS Gateway

Validates credentials and numbers, deducts credits, assigns a unique msg-id, and dispatches to the carrier.

3
Kuwait Carrier

Routed to Zain, Ooredoo, STC, or Virgin Mobile with priority routing for transactional sender IDs that bypass DND lists.

4
Message Delivered

Recipient receives the SMS within seconds. JSON response with msg-id returned immediately after dispatch.


Official Client Libraries

Native client libraries for 12 languages. Click any card to view on GitHub.

Zero boilerplate No HTTP client, headers, or JSON setup, just call send().
Phone normalization Strips +, 00, spaces, and converts Arabic digits automatically.
Message cleaning Removes emojis and hidden characters that silently block delivery.
Typed responses Access result.msgId, result.balance directly, no JSON parsing.
Error handling Descriptive exceptions with error code and description built in.
Bulk sending Pass any number of recipients, the SDK batches them into 200-per-request chunks with automatic delays.
Duplicate deduplication Automatically removes duplicate numbers from your list before sending.
Balance tracking Syncs remaining balance after every send, no extra API call.