# WebSMS API - Complete Developer Reference > This document provides everything developers need to integrate with the WebSMS API. > Token-based authentication only. Simple, modern API design. ## Base URL ``` https://websms.co.nz/api/connexus ``` --- ## Authentication WebSMS uses OAuth2-style token authentication. First, get an access token using your credentials. ### Get Access Token ``` POST /auth/token Content-Type: application/x-www-form-urlencoded ``` **Parameters:** - `client_id` (required): Your client ID from Members Area > API Keys - `client_secret` (required): Your client secret (shown once when created) **Response:** ```json { "access_token": "wst_abc123def456...", "token_type": "Bearer", "expires_in": 86400 } ``` **Notes:** - Access tokens are valid for 24 hours (86400 seconds) - When expired, request a new token using your credentials - Include token in all API requests: `Authorization: Bearer {access_token}` --- ## 1. Send SMS Send a single SMS message. ``` POST /sms/out Authorization: Bearer {token} Content-Type: application/x-www-form-urlencoded ``` **Parameters:** - `to` (required): Recipient phone number (e.g., `6421234567` for NZ, `61412345678` for AU) - `body` (required): Message text - `from` (optional): Sender ID - by default a shared shortcode is used. Set this only if you have registered your own shortcode. **Response:** ```json { "success": true, "status": "accepted", "message_id": "1188236", "to": "6421234567", "from": "552", "parts": 1, "route": "smsc_vodafone", "porting": {"ported": true, "carrier": "One NZ"} } ``` --- ## 2. Send Bulk SMS Send the same message to multiple recipients. ``` POST /sms/out Authorization: Bearer {token} Content-Type: application/json ``` **JSON Body:** ```json { "to": ["6421111111", "6422222222", "6423333333"], "body": "Your appointment is tomorrow at 2pm" } ``` **Response:** ```json { "success": true, "messages": [ { "success": true, "status": "accepted", "message_id": "1188236", "to": "64211111111", "from": "552", "parts": 1, "route": "smsc_vodafone", "porting": {"ported": true, "carrier": "One NZ"} }, { "success": true, "status": "accepted", "message_id": "1188237", "to": "64222222222", "from": "552", "parts": 1, "route": "smsc_vodafone" } ], "summary": { "total": 2, "sent": 2, "failed": 0 } } ``` --- ## 3. Send OTP (One-Time Password) Send a verification code with your company branding. ``` POST /sms/otp Authorization: Bearer {token} Content-Type: application/x-www-form-urlencoded ``` **Parameters:** - `to` (required): Recipient phone number - `company_name` (required): Your company name (appears in message) **Message sent to user:** ``` Your {company_name} verification code is: 847291 ``` **Response:** ```json { "success": true, "message_id": "msg_otp123", "code": "847291", "expires_in": 600 } ``` **Notes:** - OTP codes are 6 digits - Codes expire after 10 minutes (600 seconds) --- ## 4. Check Delivery Status Check the delivery status of a sent message. ``` GET /sms/status?message_id={message_id} Authorization: Bearer {token} ``` **Response:** ```json { "success": true, "message_id": "msg_abc123", "status": "delivered", "delivered_at": "2024-01-15T10:30:05Z", "to": "6421234567" } ``` **Possible status values:** - `queued` - Message is queued for sending - `sent` - Message sent to carrier - `delivered` - Message delivered to handset - `failed` - Message delivery failed - `expired` - Message expired (not delivered within 48 hours) --- ## 5. Webhooks (Receive SMS & Delivery Receipts) Configure a single webhook URL to receive both incoming SMS messages and delivery status updates. **Configure at:** Members Area > API Keys > Webhook URL Your webhook receives POST requests with JSON payloads. Check the `type` field to determine the event type. ### Incoming SMS Payload (type: "mo") ```json { "type": "mo", "from": "6421234567", "to": "2190", "message": "Hello, I'd like to confirm my appointment", "timestamp": "2024-01-15T10:30:00Z" } ``` ### Delivery Receipt Payload (type: "dlr") ```json { "type": "dlr", "message_id": "msg_abc123", "status": "delivered", "timestamp": "2024-01-15T10:30:05Z" } ``` **Webhook Requirements:** - Must use HTTPS - Should respond with HTTP 200 within 5 seconds - Failed webhooks are retried up to 3 times --- ## 6. Number Lookup (HLR) Validate a phone number and get carrier information. ``` GET /number/lookup?number={number} Authorization: Bearer {token} ``` **Response:** ```json { "success": true, "number": "6421234567", "valid": true, "carrier": "Spark", "country": "NZ", "type": "mobile" } ``` --- ## 7. Check Balance Get your current account balance. ``` POST /sms/balance Authorization: Bearer {token} ``` **Response:** ```json { "success": true, "balance": 45.50, "currency": "NZD" } ``` --- ## Phone Number Format Format phone numbers without the + prefix: | Country | Format | Example | |---------|--------|---------| | New Zealand | 64 + number without leading 0 | `6421234567` | | Australia | 61 + number without leading 0 | `61412345678` | | International | Country code + number | `14155551234` | **Local format conversion:** - `021 234 567` (NZ local) → `6421234567` - `0412 345 678` (AU local) → `61412345678` --- ## Message Segments & Pricing Messages are charged per segment. Segment limits depend on character encoding. ### GSM (Standard Characters) - 160 characters = 1 segment - 307 characters = 2 segments (153 chars per additional segment) - 460 characters = 3 segments ### Unicode (Emojis, Special Characters) - 70 characters = 1 segment - 134 characters = 2 segments (67 chars per additional segment) - 201 characters = 3 segments **Pricing:** - Each segment = 1 credit = $0.10 NZD --- ## Error Codes | Code | Description | |------|-------------| | 400 | Bad request - missing or invalid parameters | | 401 | Invalid or expired access token | | 403 | Insufficient balance | | 404 | Resource not found | | 429 | Rate limited (max 100 requests/second) | | 500 | Server error | **Error Response Format:** ```json { "success": false, "error": "Insufficient balance", "error_code": 403 } ``` --- ## Rate Limits - 100 requests per second per account - Bulk SMS: up to 10,000 recipients per request --- ## Code Examples ### cURL ```bash # Get access token curl -X POST https://websms.co.nz/api/connexus/auth/token \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET" # Send SMS curl -X POST https://websms.co.nz/api/connexus/sms/out \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d "to=6421234567" \ -d "body=Hello from WebSMS" # Send OTP curl -X POST https://websms.co.nz/api/connexus/sms/otp \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d "to=6421234567" \ -d "company_name=Acme Corp" # Check balance curl -X GET https://websms.co.nz/api/connexus/balance \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ### Python ```python import requests # Configuration BASE_URL = "https://websms.co.nz/api/connexus" CLIENT_ID = "your_client_id" CLIENT_SECRET = "your_client_secret" # Get access token def get_token(): response = requests.post(f"{BASE_URL}/auth/token", data={ "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET }) return response.json()["access_token"] # Send SMS def send_sms(token, to, message): headers = {"Authorization": f"Bearer {token}"} response = requests.post(f"{BASE_URL}/sms/out", headers=headers, data={ "to": to, "body": message }) return response.json() # Send OTP def send_otp(token, to, company_name): headers = {"Authorization": f"Bearer {token}"} response = requests.post(f"{BASE_URL}/sms/otp", headers=headers, data={ "to": to, "company_name": company_name }) return response.json() # Example usage token = get_token() result = send_sms(token, "6421234567", "Hello from Python!") print(result) otp_result = send_otp(token, "6421234567", "Acme Corp") print(f"OTP code: {otp_result['code']}") ``` ### Node.js ```javascript const axios = require('axios'); const BASE_URL = 'https://websms.co.nz/api/connexus'; const CLIENT_ID = 'your_client_id'; const CLIENT_SECRET = 'your_client_secret'; // Get access token async function getToken() { const response = await axios.post(`${BASE_URL}/auth/token`, { client_id: CLIENT_ID, client_secret: CLIENT_SECRET }); return response.data.access_token; } // Send SMS async function sendSms(token, to, message) { const response = await axios.post(`${BASE_URL}/sms/out`, { to: to, body: message }, { headers: { Authorization: `Bearer ${token}` } }); return response.data; } // Send OTP async function sendOtp(token, to, companyName) { const response = await axios.post(`${BASE_URL}/sms/otp`, { to: to, company_name: companyName }, { headers: { Authorization: `Bearer ${token}` } }); return response.data; } // Example usage (async () => { const token = await getToken(); const result = await sendSms(token, '6421234567', 'Hello from Node.js!'); console.log(result); const otpResult = await sendOtp(token, '6421234567', 'Acme Corp'); console.log(`OTP code: ${otpResult.code}`); })(); ``` ### PHP ```php $clientId, 'client_secret' => $clientSecret ])); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = json_decode(curl_exec($ch), true); curl_close($ch); return $response['access_token']; } // Send SMS function sendSms($baseUrl, $token, $to, $message) { $ch = curl_init("$baseUrl/sms/out"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'to' => $to, 'body' => $message ])); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer $token"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = json_decode(curl_exec($ch), true); curl_close($ch); return $response; } // Send OTP function sendOtp($baseUrl, $token, $to, $companyName) { $ch = curl_init("$baseUrl/sms/otp"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'to' => $to, 'company_name' => $companyName ])); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer $token"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = json_decode(curl_exec($ch), true); curl_close($ch); return $response; } // Example usage $token = getToken($baseUrl, $clientId, $clientSecret); $result = sendSms($baseUrl, $token, '6421234567', 'Hello from PHP!'); print_r($result); $otpResult = sendOtp($baseUrl, $token, '6421234567', 'Acme Corp'); echo "OTP code: " . $otpResult['code']; ``` ### Ruby ```ruby require 'net/http' require 'json' require 'uri' BASE_URL = 'https://websms.co.nz/api/connexus' CLIENT_ID = 'your_client_id' CLIENT_SECRET = 'your_client_secret' # Get access token def get_token uri = URI("#{BASE_URL}/auth/token") response = Net::HTTP.post_form(uri, { 'client_id' => CLIENT_ID, 'client_secret' => CLIENT_SECRET }) JSON.parse(response.body)['access_token'] end # Send SMS def send_sms(token, to, message) uri = URI("#{BASE_URL}/sms/out") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request['Authorization'] = "Bearer #{token}" request.set_form_data({ 'to' => to, 'body' => message }) response = http.request(request) JSON.parse(response.body) end # Send OTP def send_otp(token, to, company_name) uri = URI("#{BASE_URL}/sms/otp") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request['Authorization'] = "Bearer #{token}" request.set_form_data({ 'to' => to, 'company_name' => company_name }) response = http.request(request) JSON.parse(response.body) end # Example usage token = get_token result = send_sms(token, '6421234567', 'Hello from Ruby!') puts result otp_result = send_otp(token, '6421234567', 'Acme Corp') puts "OTP code: #{otp_result['code']}" ``` ### C# ```csharp using System; using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; class WebSmsClient { private const string BaseUrl = "https://websms.co.nz/api/connexus"; private readonly string _clientId; private readonly string _clientSecret; private readonly HttpClient _http = new HttpClient(); public WebSmsClient(string clientId, string clientSecret) { _clientId = clientId; _clientSecret = clientSecret; } public async Task GetTokenAsync() { var content = new FormUrlEncodedContent(new[] { new KeyValuePair("client_id", _clientId), new KeyValuePair("client_secret", _clientSecret) }); var response = await _http.PostAsync($"{BaseUrl}/auth/token", content); var json = await response.Content.ReadAsStringAsync(); var data = JsonSerializer.Deserialize(json); return data.GetProperty("access_token").GetString(); } public async Task SendSmsAsync(string token, string to, string message) { _http.DefaultRequestHeaders.Clear(); _http.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}"); var content = new FormUrlEncodedContent(new[] { new KeyValuePair("to", to), new KeyValuePair("body", message) }); var response = await _http.PostAsync($"{BaseUrl}/sms/out", content); var json = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(json); } public async Task SendOtpAsync(string token, string to, string companyName) { _http.DefaultRequestHeaders.Clear(); _http.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}"); var content = new FormUrlEncodedContent(new[] { new KeyValuePair("to", to), new KeyValuePair("company_name", companyName) }); var response = await _http.PostAsync($"{BaseUrl}/sms/otp", content); var json = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(json); } } // Example usage var client = new WebSmsClient("your_client_id", "your_client_secret"); var token = await client.GetTokenAsync(); var result = await client.SendSmsAsync(token, "6421234567", "Hello from C#!"); Console.WriteLine(result); var otpResult = await client.SendOtpAsync(token, "6421234567", "Acme Corp"); Console.WriteLine($"OTP code: {otpResult.GetProperty("code").GetString()}"); ``` ### Go ```go package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" "net/url" ) const baseURL = "https://websms.co.nz/api/connexus" type TokenResponse struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` ExpiresIn int `json:"expires_in"` } type SmsResponse struct { Success bool `json:"success"` MessageID string `json:"message_id"` } type OtpResponse struct { Success bool `json:"success"` MessageID string `json:"message_id"` Code string `json:"code"` ExpiresIn int `json:"expires_in"` } func getToken(clientID, clientSecret string) (string, error) { data := url.Values{} data.Set("client_id", clientID) data.Set("client_secret", clientSecret) resp, err := http.PostForm(baseURL+"/auth/token", data) if err != nil { return "", err } defer resp.Body.Close() var tokenResp TokenResponse json.NewDecoder(resp.Body).Decode(&tokenResp) return tokenResp.AccessToken, nil } func sendSms(token, to, message string) (*SmsResponse, error) { data := url.Values{} data.Set("to", to) data.Set("body", message) req, _ := http.NewRequest("POST", baseURL+"/sms/out", bytes.NewBufferString(data.Encode())) req.Header.Set("Authorization", "Bearer "+token) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() var smsResp SmsResponse json.NewDecoder(resp.Body).Decode(&smsResp) return &smsResp, nil } func sendOtp(token, to, companyName string) (*OtpResponse, error) { data := url.Values{} data.Set("to", to) data.Set("company_name", companyName) req, _ := http.NewRequest("POST", baseURL+"/sms/otp", bytes.NewBufferString(data.Encode())) req.Header.Set("Authorization", "Bearer "+token) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() var otpResp OtpResponse json.NewDecoder(resp.Body).Decode(&otpResp) return &otpResp, nil } func main() { token, _ := getToken("your_client_id", "your_client_secret") result, _ := sendSms(token, "6421234567", "Hello from Go!") fmt.Printf("SMS sent: %+v\n", result) otpResult, _ := sendOtp(token, "6421234567", "Acme Corp") fmt.Printf("OTP code: %s\n", otpResult.Code) } ``` --- ## Webhook Handler Examples ### Python (Flask) ```python from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/webhook', methods=['POST']) def webhook(): data = request.json if data['type'] == 'mo': # Incoming SMS print(f"SMS from {data['from']}: {data['message']}") elif data['type'] == 'dlr': # Delivery receipt print(f"Message {data['message_id']} status: {data['status']}") return jsonify({'success': True}), 200 if __name__ == '__main__': app.run(port=3000) ``` ### Node.js (Express) ```javascript const express = require('express'); const app = express(); app.use(express.json()); app.post('/webhook', (req, res) => { const data = req.body; if (data.type === 'mo') { // Incoming SMS console.log(`SMS from ${data.from}: ${data.message}`); } else if (data.type === 'dlr') { // Delivery receipt console.log(`Message ${data.message_id} status: ${data.status}`); } res.json({ success: true }); }); app.listen(3000); ``` ### PHP ```php true]); ``` --- ## Quick Start 1. **Create API Key**: Members Area > API Keys > Create New API Key 2. **Save Credentials**: Copy your Client ID and Client Secret (secret shown only once) 3. **Get Token**: POST to `/auth/token` with your credentials 4. **Send SMS**: POST to `/sms/out` with your token and message 5. **Set Webhook**: Members Area > API Keys > Webhook URL --- ## Support - Documentation: https://websms.co.nz/api/connexus/ - Contact: https://websms.co.nz/contact/