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
DATA='{
  "username": "your_api_user",
  "password": "your_api_pass",
  "sender":   "YOUR-SENDER",
  "mobile":   "96598765432",
  "message":  "Your OTP for MyApp is: 123456",
  "test":     "1"
'}'
curl -s -X POST 'https://www.kwtsms.com/API/send/' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d "$DATA"
Direct API Call kwtsms_send.php
$data = [
    'username' => 'your_api_user',
    'password' => 'your_api_pass',
    'sender'   => 'YOUR-SENDER',
    'mobile'   => '96598765432',
    'message'  => 'Your OTP for MyApp 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
use KwtSMS\Client; // composer require boxlinknet/kwtsms-php

$client = new Client('your_api_user', 'your_api_pass');

$result = $client->send([
    'sender'  => 'YOUR-SENDER',
    'mobile'  => '96598765432',
    'message' => 'Your OTP for MyApp 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": "your_api_user",
    "password": "your_api_pass",
    "sender":   "YOUR-SENDER",
    "mobile":   "96598765432",
    "message":  "Your OTP for MyApp 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 Client  # pip install kwtsms

client = Client("your_api_user", "your_api_pass")

result = client.send(
    sender="YOUR-SENDER",
    mobile="96598765432",
    message="Your OTP for MyApp 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: 'your_api_user',
    password: 'your_api_pass',
    sender:   'YOUR-SENDER',
    mobile:   '96598765432',
    message:  'Your OTP for MyApp 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-js'; // npm install kwtsms-js

const client = new KwtSMS({
  username: 'your_api_user',
  password: 'your_api_pass',
});

const result = await client.send({
  sender:  'YOUR-SENDER',
  mobile:  '96598765432',
  message: 'Your OTP for MyApp 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: 'your_api_user',
  password: 'your_api_pass',
  sender:   'YOUR-SENDER',
  mobile:   '96598765432',
  message:  'Your OTP for MyApp 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-ruby

client = KwtSMS::Client.new('your_api_user', 'your_api_pass')

result = client.send(
  sender:  'YOUR-SENDER',
  mobile:  '96598765432',
  message: 'Your OTP for MyApp 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": "your_api_user",
        "password": "your_api_pass",
        "sender":   "YOUR-SENDER",
        "mobile":   "96598765432",
        "message":  "Your OTP for MyApp 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"
    kwtsms "github.com/boxlinknet/kwtsms-go"
)

func main() {
    client := kwtsms.NewClient("your_api_user", "your_api_pass")

    result, err := client.Send(kwtsms.SendParams{
        Sender:  "YOUR-SENDER",
        Mobile:  "96598765432",
        Message: "Your OTP for MyApp is: 123456",
    })
    if err != nil {
        panic(err)
    }
    fmt.Println("Sent! Msg ID:", result.MsgID)
}
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": "your_api_user",
              "password": "your_api_pass",
              "sender":   "YOUR-SENDER",
              "mobile":   "96598765432",
              "message":  "Your OTP for MyApp 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
import com.boxlinknet.kwtsms.Client;
import com.boxlinknet.kwtsms.SendResult;

public class SendSMS {
    public static void main(String[] args) throws Exception {
        var client = new Client("your_api_user", "your_api_pass");

        SendResult result = client.send()
            .sender("YOUR-SENDER")
            .mobile("96598765432")
            .message("Your OTP for MyApp is: 123456")
            .execute();

        System.out.println("Sent! Msg ID: " + result.getMsgId());
    }
}
Direct API Call KwtsmsSend.cs
using System.Net.Http;
using System.Text;
using System.Text.Json;

var payload = new {
    username = "your_api_user",
    password = "your_api_pass",
    sender   = "YOUR-SENDER",
    mobile   = "96598765432",
    message  = "Your OTP for MyApp 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; // NuGet: KwtSMS.Client

var client = new KwtSMSClient("your_api_user", "your_api_pass");

var result = await client.SendAsync(new SendRequest {
    Sender  = "YOUR-SENDER",
    Mobile  = "96598765432",
    Message = "Your OTP for MyApp is: 123456",
});

if (result.IsSuccess) {
    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": "your_api_user",
        "password": "your_api_pass",
        "sender":   "YOUR-SENDER",
        "mobile":   "96598765432",
        "message":  "Your OTP for MyApp 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::Client; // kwtsms = "1"

#[tokio::main]
async fn main() {
    let client = Client::new("your_api_user", "your_api_pass");

    let result = client.send()
        .sender("YOUR-SENDER")
        .mobile("96598765432")
        .message("Your OTP for MyApp is: 123456")
        .execute().await.unwrap();

    println!("Sent! Msg ID: {}", result.msg_id);
}
Direct API Call KwtsmsSend.kt
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import org.json.JSONObject

fun main() {
    val payload = JSONObject()
        .put("username", "your_api_user")
        .put("password", "your_api_pass")
        .put("sender",   "YOUR-SENDER")
        .put("mobile",   "96598765432")
        .put("message",  "Your OTP for MyApp 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
import com.boxlinknet.kwtsms.Client // implementation("com.boxlinknet:kwtsms-kotlin:1.0")

suspend fun main() {
    val client = Client("your_api_user", "your_api_pass")

    val result = client.send(
        sender  = "YOUR-SENDER",
        mobile  = "96598765432",
        message = "Your OTP for MyApp is: 123456"
    )

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

let payload: [String: Any] = [
    "username": "your_api_user",
    "password": "your_api_pass",
    "sender":   "YOUR-SENDER",
    "mobile":   "96598765432",
    "message":  "Your OTP for MyApp 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", from: "1.0.0")
import KwtSMS

let client = KwtSMSClient(username: "your_api_user", password: "your_api_pass")

let result = try await client.send(
    sender:  "YOUR-SENDER",
    mobile:  "96598765432",
    message: "Your OTP for MyApp is: 123456"
)

if result.isSuccess {
    print("Sent! Msg ID: \(result.msgId)")
} else {
    print("Error: \(result.code)")
}
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': 'your_api_user',
      'password': 'your_api_pass',
      'sender':   'YOUR-SENDER',
      'mobile':   '96598765432',
      'message':  'Your OTP for MyApp is: 123456',
      'test':     '1',
    }),
  );
  print(resp.body);
}
Using Dart SDK SDK kwtsms_sdk.dart
import 'package:kwtsms/kwtsms.dart'; // pubspec.yaml: kwtsms: ^1.0.0

void main() async {
  final client = KwtSMS('your_api_user', 'your_api_pass');

  final result = await client.send(
    sender:  'YOUR-SENDER',
    mobile:  '96598765432',
    message: 'Your OTP for MyApp is: 123456',
  );

  if (result.isSuccess) {
    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(.{}){};
    const alloc = gpa.allocator();
    var client = std.http.Client{ .allocator = alloc };
    defer client.deinit();

    const body =
        \\{"username":"your_api_user","password":"your_api_pass",
        \\ "sender":"YOUR-SENDER","mobile":"96598765432",
        \\ "message":"Your OTP for MyApp is: 123456","test":"1"}
    ;

    var buf: [4096]u8 = undefined;
    const result = 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 = .{ .static = &buf },
    });
    std.debug.print("{s}\n", .{ buf[0..result.bytes_read] });
}
Using Zig SDK SDK kwtsms_sdk.zig
// build.zig.zon: .kwtsms = .{ .url = "https://github.com/boxlinknet/kwtsms-zig/..." }
const kwtsms = @import("kwtsms");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const client = kwtsms.Client.init(
        gpa.allocator(), "your_api_user", "your_api_pass"
    );

    const result = try client.send(.{
        .sender  = "YOUR-SENDER",
        .mobile  = "96598765432",
        .message = "Your OTP for MyApp is: 123456",
    });

    std.debug.print("Sent! Msg ID: {s}\n", .{ result.msg_id });
}
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 => 'your_api_user',
        password => 'your_api_pass',
        sender   => 'YOUR-SENDER',
        mobile   => '96598765432',
        message  => 'Your OTP for MyApp 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.

View all repositories on GitHub