How To Send SMS Text Messages in C# and ASP.NET Core



Last updated: October 28th, 2026

Updated October 2026: the original 2013 Nexmo example used an API and libraries that no longer exist. This version uses current .NET with the Twilio SDK, a no-SDK HttpClient version, and an injectable service for ASP.NET Core. Every sample compiles on .NET 8 and .NET 10.

Quick Answer

To send an SMS from C#, sign up with an SMS API provider, buy a phone number, and make one authenticated HTTP request. With Twilio's NuGet package it is three lines:

using Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

// dotnet add package Twilio
string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID")!;
string authToken = Environment.GetEnvironmentVariable("TWILIO_AUTH_TOKEN")!;

TwilioClient.Init(accountSid, authToken);

MessageResource message = await MessageResource.CreateAsync(
    to: new PhoneNumber("+13055550123"),     // E.164 format: +, country code, number
    from: new PhoneNumber("+13055550199"),   // your Twilio number (or use messagingServiceSid:)
    body: "Order #1042 was placed. Details: https://example.com/admin/orders/1042");

Console.WriteLine($"{message.Sid} {message.Status}"); // e.g. SMxxxxxxxx queued

Phone numbers must be in E.164 format: a plus sign, the country code, then the number with no spaces or dashes (for example +13055550123 for a US number).

What You Need

  • An SMS provider account. Twilio is used below; Vonage (formerly Nexmo), Amazon SNS / AWS End User Messaging, Azure Communication Services, Plivo and Telnyx all work the same way: an HTTPS API call with your credentials.
  • A sending number from that provider, enabled for SMS.
  • Your credentials (for Twilio, the Account SID and Auth Token, or an API key). Keep them in environment variables or user secrets, never in source code.
  • US only: registration. US carriers require A2P 10DLC brand and campaign registration for messages from standard 10-digit numbers, and toll-free verification for toll-free numbers. Unregistered traffic is filtered or blocked, so do this before you go live. It usually takes days, not minutes.

Sending SMS With HttpClient (No SDK)

If you don't want another dependency, Twilio's REST API is a form POST with HTTP Basic authentication. This is also handy for seeing exactly what goes over the wire:

using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

// No SDK: Twilio's REST API is a form POST with HTTP Basic auth.
string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID")!;
string authToken = Environment.GetEnvironmentVariable("TWILIO_AUTH_TOKEN")!;

using var http = new HttpClient();
string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{accountSid}:{authToken}"));
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);

var form = new FormUrlEncodedContent(new Dictionary<string, string>
{
    ["To"] = "+13055550123",
    ["From"] = "+13055550199",
    ["Body"] = "Your verification code is 482913"
});

using HttpResponseMessage response = await http.PostAsync(
    $"https://api.twilio.com/2010-04-01/Accounts/{accountSid}/Messages.json", form);

string json = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
    // Twilio errors include a numeric "code" (e.g. 21211 = invalid 'To' number).
    throw new HttpRequestException($"Twilio returned {(int)response.StatusCode}: {json}");
}

using JsonDocument doc = JsonDocument.Parse(json);
Console.WriteLine($"Sent: {doc.RootElement.GetProperty("sid").GetString()}");

Sending SMS From ASP.NET Core

In a web app, wrap the provider behind an interface so controllers don't depend on Twilio directly, settings come from configuration, and you can swap providers or fake the sender in tests:

// A small service you can inject anywhere in an ASP.NET Core app.
using Microsoft.Extensions.Options;
using Twilio.Clients;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

public sealed class SmsOptions
{
    public string AccountSid { get; set; } = "";
    public string AuthToken { get; set; } = "";
    public string FromNumber { get; set; } = "";
}

public interface ISmsSender
{
    Task<string> SendAsync(string toE164, string text);
}

public sealed class TwilioSmsSender : ISmsSender
{
    private readonly TwilioRestClient _client;
    private readonly string _from;

    public TwilioSmsSender(IOptions<SmsOptions> options)
    {
        SmsOptions o = options.Value;
        _client = new TwilioRestClient(o.AccountSid, o.AuthToken);
        _from = o.FromNumber;
    }

    public async Task<string> SendAsync(string toE164, string text)
    {
        MessageResource message = await MessageResource.CreateAsync(
            to: new PhoneNumber(toE164),
            from: new PhoneNumber(_from),
            body: text,
            client: _client);

        return message.Sid;
    }
}

// Program.cs:
// builder.Services.Configure<SmsOptions>(builder.Configuration.GetSection("Sms"));
// builder.Services.AddSingleton<ISmsSender, TwilioSmsSender>();

Then inject ISmsSender wherever you need it, for example to text yourself when a new order arrives:

await smsSender.SendAsync("+13055550123", $"New order #{order.Id}: https://example.com/admin/orders/{order.Id}");

If messages are triggered by user actions (sign-ups, password resets), send them from a background queue rather than inside the request, and rate-limit them. SMS endpoints are a favorite target for "SMS pumping" fraud, where bots trigger texts to premium numbers at your expense.

Practical Tips

  • Message length: one SMS segment holds 160 GSM-7 characters, or 70 if the text contains emoji or other Unicode characters. Longer messages are split into multiple billed segments.
  • Costs: you typically pay a small monthly fee per number plus a per-segment price that varies by country, and US registration has its own fees. Check your provider's pricing page.
  • Delivery status: the API response only means the message was accepted. To know whether it was delivered, set a status callback URL and record the updates.
  • Opt-outs: recipients can reply STOP; providers block further messages to them automatically. Only text people who have agreed to receive messages.
  • Two-factor codes: for verification codes, use a purpose-built verification API (such as Twilio Verify) rather than sending codes yourself; it handles retries, expiry and fraud checks.

The Original 2013 Approach

This post originally showed how I sent an SMS to a Google Voice number whenever a new order came in, using Nexmo's HTTP GET API (rest.nexmo.com/sms/json?username=...&password=...) with WebClient and JavaScriptSerializer. Nexmo is now Vonage, credentials in a query string are no longer accepted practice, and those .NET classes are obsolete, so the examples above replace it. The idea is the same: one authenticated HTTP call per message.

Frequently Asked Questions

How do I send a text message from C#?

Use an SMS API provider. Install its NuGet package (for example Twilio), initialize it with your credentials, and call its send method with the destination number in E.164 format, your sending number and the message text.

Can I send SMS from C# for free?

Not reliably. Providers offer trial credit, but sending real SMS costs money because carriers charge for delivery. Email-to-SMS gateways used to be a free workaround, but carriers have been shutting them down and they were never dependable.

Do I need a GSM modem to send SMS from .NET?

No. A cloud SMS API is simpler, more reliable and works from any server. GSM modems are only worth it for special offline or very high-volume cases.

What is A2P 10DLC?

It is the US carrier registration system for application-to-person messages sent from standard 10-digit long-code numbers. You register your business (brand) and use case (campaign) through your SMS provider; unregistered messages are filtered.

Summary

Sending SMS from C# is a single authenticated HTTPS request: use the provider's SDK or HttpClient, format numbers as E.164, keep credentials in configuration, and complete US registration before sending at scale.

Related: sending email with the Mailchimp Transactional API in C#.


Comments

No Comments

CAPTCHA

Tagged: ASP.NET, C Sharp


Join my email list!



ryan
About Me

With over 15 years in tech, I've excelled as a senior software engineer, specializing in ASP.NET, C#, SQL, Azure, and front-end technologies. I've led diverse projects across various sectors, from startups to global corporations, particularly during my decade in the San Francisco Bay Area.


Sign Up Hostinger Email