.NET
The Divergent.Connect package sends and manages SMS and email with the v2 API. It supports .NET 8, 9 and 10, and .NET Standard 2.0.
Installing
Section titled “Installing”dotnet add package Divergent.Connect --prereleaseVersion 2.0 and later is for the v2 API. The 0.5.x versions are for the v1 API.
To receive webhooks in ASP.NET Core, add Divergent.Connect.AspNetCore too.
Setting up with dependency injection
Section titled “Setting up with dependency injection”Register the client in Program.cs:
using Divergent.Connect.DependencyInjection;
builder.AddDivergentConnect();It reads its settings from the Divergent:Connect section of your configuration, for example in appsettings.json:
{ "Divergent": { "Connect": { "ApiKey": "ck_...", "DefaultSmsSender": "YourBrand", "DefaultEmailSender": "hello@yourcompany.com" } }}Keep your API key out of source control, for example in user secrets or an environment variable named Divergent__Connect__ApiKey.
| Setting | Description |
|---|---|
ApiKey | Your v2 API key. Required |
DefaultSmsSender | Used when an SMS or batch doesn’t set Sender |
DefaultEmailSender | Used when an email doesn’t set Sender |
ApiKeyId, SigningSecret | Signs every request, for keys that need signed requests |
ApiUrl | Defaults to https://api.connect.ms/ |
You can also change settings in code with builder.AddDivergentConnect(o => ...), or use services.AddDivergentConnect(configuration) without a host builder.
Then inject ConnectClient, or just ConnectSms or ConnectEmail:
public class OrderNotifier(ConnectSms sms){ public Task ShippedAsync(string phone) => sms.SendAsync(new SendSmsRequest { Recipient = phone, Content = "Your order has shipped." });}Setting up without dependency injection
Section titled “Setting up without dependency injection”var connect = new ConnectClientBuilder() .WithApiKey(apiKey) .WithDefaultSmsSender("YourBrand") .Build();The builder also has WithDefaultEmailSender, WithSigning, WithSigningKey, WithApiUrl, WithHttpClient and WithLoggerFactory. Create one client and reuse it.
Sending SMS
Section titled “Sending SMS”using Divergent.Connect.Models;
var sms = await connect.Sms.SendAsync(new SendSmsRequest{ Recipient = "+447700900123", Content = "Hi Sam, your order has shipped.",});
Console.WriteLine($"{sms.Id} {sms.Status}");The request and the returned message are the same as the API’s. See Send SMS and Track SMS.
| Method | API |
|---|---|
Sms.SendAsync | POST /v2/sms |
Sms.GetAsync | GET /v2/sms/{id} |
Sms.ListAsync, Sms.ListAllAsync | GET /v2/sms |
Sms.CancelAsync | DELETE /v2/sms/{id} |
Sms.CreateBatchAsync, Sms.GetBatchAsync, Sms.CancelBatchAsync | Batches |
Sending email
Section titled “Sending email”await connect.Email.SendAsync(new SendEmailRequest{ Recipient = "sam@example.com", Subject = "Your order has shipped", Content = new() { Html = "<p>Hi Sam, your order is on its way.</p>" }, Attachments = [EmailAttachment.FromBytes("receipt.pdf", "application/pdf", pdfBytes)],});See Send Email. Email has SendAsync, GetAsync, ListAsync, ListAllAsync and CancelAsync, like Sms.
Listing
Section titled “Listing”ListAsync returns one page, with Data and NextCursor. Set Cursor to NextCursor for the next page. ListAllAsync fetches every page for you:
await foreach (var message in connect.Sms.ListAllAsync(new ListSmsOptions { Status = SmsMessageStatus.Failed })) Console.WriteLine($"{message.Id} {message.Reason?.Code}");Retries
Section titled “Retries”Every POST has an Idempotency-Key, so a retry never sends twice. The client makes one up, or you can pass your own:
await connect.Sms.SendAsync(request, idempotencyKey: "order-991-shipped");Network errors, 5xx and 429 responses are retried twice, waiting for Retry-After when there is one.
Errors
Section titled “Errors”Any other error throws a ConnectApiException:
try{ await connect.Sms.SendAsync(request);}catch (ConnectApiException e){ Console.WriteLine($"{e.Status} {e.Code} {e.Detail} {e.RequestId}");}Errors lists validation problems by field. Quote RequestId when you contact support.
Next steps
Section titled “Next steps”To receive events, see ASP.NET Core webhooks.