C#: Parse DLR from an Android SMS Gateway API

Featured illustration for C#: Parse DLR from an Android SMS Gateway API

Parse DLR in C# for an Android SMS Gateway API: HowTo, mapper sample, feature adjacency, and downloads/questions links.

Written by the SMS Gateway team for operators who run phones and airtime themselves — not for theoretical cloud SMS demos.

InformationAndroid SMS GatewayAPIDevelopers
Article
Published
June 18, 2026
Updated
July 8, 2026
Reading time
17 minute read

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#

  1. Persist messages[].id.
  2. GET that id or wait for webhook.
  3. Map status / deliveredAt.
  4. 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 seeMeansYour row
PendingQueued / not yet radiosent_pending
DeliveredCarrier DLR when provideddelivered
FailedRadio or SMSC gave upfailed — 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.

Jump to the live product docs for this topic—not another long-form article.

FAQ

Frequently asked questions

Direct answers about android sms gateway api.

How do I parse DLR from an Android SMS gateway API in C#?

Store the message id from the send batch. GET /messages/{id} with Bearer auth, or handle message.delivered / message.failed webhooks. Map status with System.Text.Json. Verify HMAC on webhooks.

Is Pending a failure?

No. Pending means the control plane accepted the job. The radio may not have sent yet.

Should I poll forever?

No. Webhooks in production; poll as break-glass or for a single support ticket.

Does a failed DLR refund SMS?

Operator airtime may already be spent. Free is 300 SMS lifetime on the platform.
Keep learning

Topically related guides—chosen by subject overlap, not a fixed sitewide footer.

Information
what is dlr

What Is DLR? Android SMS Gateway Context

What Is DLR? Android SMS Gateway Context. Glossary-style explainer of DLR specifically as it applies to Android SIM-based gateways versus aggregator APIs. Priced by devices and SMS send volume; BYO phone and operator credit.

Jan 26, 202616 min
Read article

Browse the full Android SMS gateway knowledge base or return to how an Android SMS gateway works.

Get started

Test the gateway on your own Android phone

Install the app, pair one device, and validate your API flow before choosing a paid plan.

You supply the phone, SIM, and operator SMS credit.