KedaSMS
From account creation to usage policies, follow these steps to launch in minutes.
Utilisez les boutons ci-dessous pour afficher le guide dans une autre langue.
Traffic is separated between the console, the edge proxy and protected backends. Allow the following origins before onboarding.
https://www.kedasms.net
Console & landing site (KedaSMS UI)https://www.kedasms.net/api
Frontend proxy (/api/*) that receives encrypted requests and forwards to the backendhttps://www.kedasms.net/docs
Hosted quickstart and API referenceSign up and verify your email address so the console can issue an API key.
Submit AES-GCM encrypted payloads through the frontend proxy. Credit is reserved instantly and debited once the carrier confirms delivery.
POST https://www.kedasms.net/api/sms/send Content-Type: application/json { "apiKey": "your-api-key", "timestamp": 1712123456, "iv": "base64-iv==", "cipherText": "base64-ciphertext==" }
{ "code": "0", "message": "Success", "data": { "taskId": "20240408-0001", "message": "SMS task created", "debitedAmount": 0.048, "currency": "USD" } }
The response includes the task ID and the amount debited from your account for full traceability.
Both endpoints return JSON that can be embedded directly into your landing pages or BI dashboards.
Stay compliant with your budget by setting per-day SMS and spend caps.
PUT https://backup.kedasms.net/api/external/accounts/limits Content-Type: application/json { "apiKey": "your-api-key", "dailySmsCap": 5000, "dailySpendCap": 200, "alertThreshold": 0.8, "blockOnLimit": true }
The limits apply to API-triggered sends and console campaigns in real time.
Query SMS delivery status with real-time updates.
GET https://backup.kedasms.net/api/sms/status?msgid=msg_abc123def456 { "success": true, "data": { "msgid": "msg_abc123def456", "status": "DELIVERED", "recipient": "+12065550123", "sender": "KedaSMS", "message": "Your verification code is 123456", "sent_time": "2024-01-01T12:00:00Z", "delivered_time": "2024-01-01T12:00:05Z" }, "code": 200 }
Receive real-time notifications for SMS status changes, supporting status callbacks and link click callbacks.
POST https://backup.kedasms.net/api/sms/callback/KEDA Content-Type: application/json { "msgid": "msg_abc123def456", "status": "DELIVERED", "recipient": "+12065550123", "sender": "KedaSMS", "sent_time": "2024-01-01T12:00:00Z", "delivered_time": "2024-01-01T12:00:05Z", "cost": "0.05" }
Encrypt the short link payload the same way and call /api/shortlinks to obtain trackable URLs.
POST https://www.kedasms.net/api/shortlinks Content-Type: application/json { "apiKey": "your-api-key", "timestamp": 1712123456, "iv": "base64-iv==", "cipherText": "base64-ciphertext==" }
Les exemples ci-dessous chiffrent la charge utile, ajoutent le timestamp en AAD et l'envoient en HTTPS vers le proxy frontal.
import base64 import json import os import time import requests from Crypto.Cipher import AES api_key = "your-api-key" encryption_key = base64.b64decode("YOUR_ENCRYPTION_KEY_BASE64") payload = { "countryCode": "CN", "phoneNumbers": ["13800138000"], "content": "您的验证码为 123456", "senderId": "KedaSMS", "trackClick": True, "callbackUrl": "https://example.com/webhook/sms" } iv = os.urandom(12) timestamp = int(time.time()) cipher = AES.new(encryption_key, AES.MODE_GCM, nonce=iv) cipher.update(timestamp.to_bytes(8, "big")) ciphertext, tag = cipher.encrypt_and_digest(json.dumps(payload).encode("utf-8")) body = { "apiKey": api_key, "timestamp": timestamp, "iv": base64.b64encode(iv).decode(), "cipherText": base64.b64encode(ciphertext + tag).decode() } response = requests.post( "https://www.kedasms.net/api/sms/send", json=body, timeout=10 ) response.raise_for_status() print(response.json())
SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode("YOUR_ENCRYPTION_KEY_BASE64"), "AES"); byte[] iv = SecureRandom.getInstanceStrong().generateSeed(12); long timestamp = Instant.now().getEpochSecond(); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); GCMParameterSpec spec = new GCMParameterSpec(128, iv); cipher.init(Cipher.ENCRYPT_MODE, keySpec, spec); cipher.update(ByteBuffer.allocate(Long.BYTES).putLong(timestamp).array()); ObjectMapper objectMapper = new ObjectMapper(); String json = objectMapper.writeValueAsString(payload); byte[] encrypted = cipher.doFinal(json.getBytes(StandardCharsets.UTF_8)); Map<String, Object> body = Map.of( "apiKey", "your-api-key", "timestamp", timestamp, "iv", Base64.getEncoder().encodeToString(iv), "cipherText", Base64.getEncoder().encodeToString(encrypted) ); String requestBody = objectMapper.writeValueAsString(body); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://www.kedasms.net/api/sms/send")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
package main import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "encoding/binary" "encoding/json" "log" "net/http" "time" ) func main() { apiKey := "your-api-key" payload := map[string]any{ "countryCode": "CN", "phoneNumbers": []string{"13800138000"}, "content": "您的验证码为 123456", "senderId": "KedaSMS", "trackClick": true, "callbackUrl": "https://example.com/webhook/sms", } key, err := base64.StdEncoding.DecodeString("YOUR_ENCRYPTION_KEY_BASE64") if err != nil { log.Fatal(err) } iv := make([]byte, 12) if _, err := rand.Read(iv); err != nil { log.Fatal(err) } block, err := aes.NewCipher(key) if err != nil { log.Fatal(err) } gcm, err := cipher.NewGCM(block) if err != nil { log.Fatal(err) } timestamp := time.Now().Unix() aad := make([]byte, 8) binary.BigEndian.PutUint64(aad, uint64(timestamp)) plaintext, err := json.Marshal(payload) if err != nil { log.Fatal(err) } ct := gcm.Seal(nil, iv, plaintext, aad) body := map[string]any{ "apiKey": apiKey, "timestamp": timestamp, "iv": base64.StdEncoding.EncodeToString(iv), "cipherText": base64.StdEncoding.EncodeToString(ct), } bodyBytes, err := json.Marshal(body) if err != nil { log.Fatal(err) } req, err := http.NewRequest(http.MethodPost, "https://www.kedasms.net/api/sms/send", bytes.NewReader(bodyBytes)) if err != nil { log.Fatal(err) } req.Header.Set("Content-Type", "application/json") client := &http.Client{Timeout: 10 * time.Second} resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() if resp.StatusCode >= 400 { log.Fatalf("unexpected status: %s", resp.Status) } }
<?php $apiKey = 'your-api-key'; $encryptionKey = base64_decode('YOUR_ENCRYPTION_KEY_BASE64'); $payload = [ 'countryCode' => 'CN', 'phoneNumbers' => ['13800138000'], 'content' => '您的验证码为 123456', 'senderId' => 'KedaSMS', 'trackClick' => true, 'callbackUrl' => 'https://example.com/webhook/sms', ]; $iv = random_bytes(12); $timestamp = time(); $aad = pack('N2', $timestamp >> 32, $timestamp & 0xffffffff); $ciphertext = openssl_encrypt( json_encode($payload, JSON_UNESCAPED_UNICODE), 'aes-256-gcm', $encryptionKey, OPENSSL_RAW_DATA, $iv, $tag, $aad ); if ($ciphertext === false) { throw new RuntimeException('encryption failed'); } $body = [ 'apiKey' => $apiKey, 'timestamp' => $timestamp, 'iv' => base64_encode($iv), 'cipherText' => base64_encode($ciphertext . $tag), ]; $ch = curl_init('https://www.kedasms.net/api/sms/send'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode($body), CURLOPT_TIMEOUT => 10, ]); $response = curl_exec($ch); if ($response === false) { throw new RuntimeException(curl_error($ch)); } $httpStatus = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); if ($httpStatus >= 400) { throw new RuntimeException('unexpected status: ' . $httpStatus); } echo $response;
Générez toujours un IV de 12 octets par requête et conservez un timestamp en secondes Unix UTC avec une dérive maximale de ±5 minutes.
Follow the operational best practices to keep delivery stable.