Key Takeaways
- Parsing DLR in C# for an Android SMS gateway API means mapping message.status from GET /messages/{id} or webhook payloads — not treating HTTP 202 as delivered.
- Confirm enum strings in Developer Center. Do not freeze a guessed list in a NuGet wrapper.
- Deduplicate webhook event ids before updating rows.
- Samples on /codebase-csharp are REST examples, not a Complete SDK.
- You bring phones and airtime. Failed DLR does not cash out operator credit.
C# parse DLR on an android sms gateway api is mapping delivery state after the SIM transmitted — or failed to. Product: delivery reports. Samples: C# REST examples. Docs: Developer Center.
You bring the Android and airtime. We meter devices and volume.
Pending → Delivered (when the carrier says so)
Accepted is not delivered
Send returns a batch with Pending:
{
"campaignId": 17,
"accepted": 1,
"scheduledAt": null,
"messages": [
{
"id": 41822,
"number": "+14155552671",
"text": "Your verification code is 481920",
"type": "sms",
"status": "Pending",
"campaignId": 17,
"deviceId": 3
}
]
}If you mark the user “notified” on 202, you will debug ghost OTPs that never left the dock.
How to parse DLR in C#
- Persist
messages[].id. - GET that id or wait for webhook.
- Map
status/deliveredAt. - Do not treat DLR as login success.
GET /messages/{id}
curl -X GET "https://app.sms-gateway.app/api/v1/messages/41822" \
-H "Authorization: Bearer $SMS_GATEWAY_API_KEY"Confirm the GET body in docs. The sketch below assumes a message object — match OpenAPI, do not invent properties.
Status map
| You see | Means | Your row |
|---|---|---|
| Pending | Queued / not yet radio | sent_pending |
| Delivered | Carrier DLR when provided | delivered |
| Failed | Radio or SMSC gave up | failed — inspect, don’t auto-resend without a new key |
API overview. JsonDocument: System.Text.Json.
Prefer webhooks
{
"id": "evt_01K2F8QW3N4RXB7M",
"type": "message.delivered",
"createdAt": "2026-08-12T14:04:09Z",
"apiVersion": "2026-08-12",
"data": {
"message": {
"id": 41823,
"number": "+14155552671",
"text": "Your verification code is 481920",
"status": "Delivered",
"campaignId": 17,
"deviceId": 3,
"metadata": { "orderId": "1234" },
"sentAt": "2026-08-12T14:04:02Z",
"deliveredAt": "2026-08-12T14:04:09Z"
}
}
}HMAC + event-id unique. Server webhook · /webhook.
Mapper sketch
using System.Net.Http.Headers;
using System.Text.Json;
public sealed record GatewayMessage(int Id, string Status, string Number);
public static async Task<GatewayMessage?> GetDlrAsync(HttpClient http, string apiKey, int id)
{
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
using var res = await http.GetAsync(quot;https://app.sms-gateway.app/api/v1/messages/{id}");
res.EnsureSuccessStatusCode();
using var doc = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
var root = doc.RootElement;
// Confirm the live JSON shape in Developer Center — this is a mapper sketch.
var status = root.GetProperty("status").GetString() ?? "Unknown";
var number = root.TryGetProperty("number", out var n) ? n.GetString() ?? "" : "";
return new GatewayMessage(id, status, number);
}OTP send path: ASP.NET OTP.
DLR is not a refund
Failed after the SIM fired still cost airtime. Free: 300 SMS lifetime. Developer: 25,000/year. Starter/Pro/Business uncap platform volume, devices 2/5/15. Pause on Free/Developer at allowance. No unlimited carrier SMS. Pricing.
Checklist
- Message id stored before you return to the user.
- Webhook HMAC in production; poll only as fallback.
- Status switch exhaustive + default log.
- No auto-resend loop on Failed.
Next steps
Send one staff SMS, GET the id, then fire a webhook into a test controller. Downloads.
Related product pages
Jump to the live product docs for this topic—not another long-form article.
- SMS delivery reports (DLR)Delivery status tracking
- SMS API documentationLive endpoint reference
- C# REST send samplesC# code examples
- device and SMS volume pricingPlans and allowances




