Get message status
Copy page
Check the delivery status of a sent message.
GET
/api/v1/sms/status/:message_id
· Permission: sms.read
Request
Section titled “Request”curl https://restlink23telecom.com/api/v1/sms/status/api_42_1743667200123456789_a3f8b2c1d9e45f67 \ -H "X-API-Key: $API_KEY"const res = await fetch('https://restlink23telecom.com/api/v1/sms/status/api_42_1743667200123456789_a3f8b2c1d9e45f67', { method: 'GET', headers: { 'X-API-Key': process.env.API_KEY },});
if (!res.ok) { const err = await res.json(); throw new Error(`${err.error_code}: ${err.description}`);}const data = await res.json();console.log(data);import osimport requests
res = requests.get( "https://restlink23telecom.com/api/v1/sms/status/api_42_1743667200123456789_a3f8b2c1d9e45f67", headers={"X-API-Key": os.environ["API_KEY"]},)res.raise_for_status()print(res.json())<?php$ch = curl_init('https://restlink23telecom.com/api/v1/sms/status/api_42_1743667200123456789_a3f8b2c1d9e45f67');curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('API_KEY')],]);
$response = curl_exec($ch);$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);curl_close($ch);
if ($status !== 200) { throw new Exception("HTTP $status: $response");}$data = json_decode($response, true);print_r($data);require "net/http"require "json"
uri = URI("https://restlink23telecom.com/api/v1/sms/status/api_42_1743667200123456789_a3f8b2c1d9e45f67")req = Net::HTTP::Get.new(uri)req["X-API-Key"] = ENV.fetch("API_KEY")
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }raise "HTTP #{res.code}: #{res.body}" unless res.is_a?(Net::HTTPSuccess)
puts JSON.parse(res.body)import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://restlink23telecom.com/api/v1/sms/status/api_42_1743667200123456789_a3f8b2c1d9e45f67")) .header("X-API-Key", System.getenv("API_KEY")) .GET() .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());System.out.println(response.body());package main
import ( "fmt" "io" "net/http" "os")
func main() { req, err := http.NewRequest("GET", "https://restlink23telecom.com/api/v1/sms/status/api_42_1743667200123456789_a3f8b2c1d9e45f67", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("API_KEY"))
res, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer res.Body.Close()
data, _ := io.ReadAll(res.Body) fmt.Println(string(data))}using System.Text;
using var client = new HttpClient();client.DefaultRequestHeaders.Add("X-API-Key", Environment.GetEnvironmentVariable("API_KEY"));
var response = await client.GetAsync("https://restlink23telecom.com/api/v1/sms/status/api_42_1743667200123456789_a3f8b2c1d9e45f67");
response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());Response
Section titled “Response”{ "status": true, "message": { "message_id": "api_42_1743667200123456789_a3f8b2c1d9e45f67", "telecom_message_id": "6946d0f5-040b-106e-42c7-49026f2b5bc1", "recipient": "+14155551234", "segments": 1, "message": "Your verification code is 847291", "sender_id": "MyApp", "status": "DELIVRD", "status_code": "000", "cost": 0.0085, "created_at": "2026-02-13T10:30:00Z", "delivered_at": "2026-02-13T10:30:04Z" }}Returns 404 NOT_FOUND if the message does not exist or belongs to another
account.
Status values
Section titled “Status values”| Status | Description | Final? |
|---|---|---|
pending | Queued, waiting to send | No |
sent | Submitted to carrier network | No |
ENROUTE | Accepted by carrier, in transit | No |
ACCEPTD | Accepted by carrier for delivery | No |
DELIVRD | Delivered to recipient’s handset | Yes |
UNDELIV | Delivery failed (invalid number, phone off) | Yes |
REJECTD | Rejected by carrier (filtered, blacklisted) | Yes |
EXPIRED | Delivery timed out | Yes |
DELETED | Message deleted on the carrier network | Yes |
UNKNOWN | Final status unknown | Yes |
failed | Internal error (queue/config failure) | Yes |
Raw carrier statuses (ENROUTE, ACCEPTD, DELETED) can appear verbatim —
treat any status not in your known set as non-final and keep polling, except
the clearly terminal ones above. See delivery statuses
for typical status flows.
When filtering the message list by status, the accepted
filter values are delivered, undelivered, expired, pending,
not_billed and sent (legacy aliases failed and unknown map to
undelivered) — these map to groups of the raw statuses above.
Polling guidance
Section titled “Polling guidance”If you poll instead of using webhooks:
- Poll every 3–5 seconds, stop on any final status.
- Give up after a few minutes and treat the message as in-flight — some carriers report late; the hourly reconciliation will finalize stuck messages.
- Prefer webhooks for anything beyond low-volume testing: they remove polling load and deliver statuses the moment carriers report them.