SendAfrica logoSendAfricaDocs

C# (.NET) SDK

NuGet SendAfrica — fully async typed client targeting .NET 8 and .NET Standard 2.0, with HMAC webhook verification and bulk sending.


PackageSendAfrica on NuGet · v1.0.1 · stable
Installdotnet add package SendAfrica
Targets.NET 8.0+ and .NET Standard 2.0
StyleFully async — all methods return Task

Idiomatic .NET patterns throughout: typed response classes, automatic retry with exponential backoff on 429/5xx, local phone normalization to E.164, and HMAC-SHA256 webhook verification. Works in console apps, ASP.NET, and background services.

#Installation

install.sh
bash
dotnet add package SendAfrica

In Visual Studio: right-click project → Manage NuGet Packages → search "SendAfrica".

#Client setup

Auth.cs
csharp
using SendAfrica;

// Option 1: explicit key
var client = new SendAfricaClient("SA-xxxxx");

// Option 2: set env var, then no arguments needed
// setx SENDAFRICA_API_KEY "SA-xxxxx"
var client = new SendAfricaClient();

// Full configuration
var client = new SendAfricaClient(
    apiKey: "SA-xxxxx",
    baseUrl: "https://api.sendafrica.online/v1",
    timeoutSeconds: 10,
    maxRetries: 3,
    environment: "production",
    debug: false,
    webhookSecret: null
);

#Sending SMS

Send.cs
csharp
var result = await client.Sms.SendAsync(
    to: "0712345678",
    message: "Your OTP is 123456",
    sender: "MyBrand"  // optional, max 11 chars
);

Console.WriteLine(result.MessageId);    // "SA-abc123..."
Console.WriteLine(result.Status);       // "Success"
Console.WriteLine(result.CreditsUsed);  // 1

// Preview cost without sending (zero network calls)
var analysis = client.Sms.Analyze("Habari, how are you?");
Console.WriteLine($"{analysis.Encoding}: {analysis.Parts} part(s)");

#Bulk sending

Bulk.cs
csharp
var results = await client.Sms.SendManyAsync(new[]
{
    new BulkSmsMessage { To = "0711111111", Message = "Hello John" },
    new BulkSmsMessage { To = "0722222222", Message = "Hello Mary" },
}, sender: "MyBrand");

Console.WriteLine($"{results.SentCount} sent, {results.FailedCount} failed");

foreach (var failure in results.Failed)
{
    Console.WriteLine($"Could not send to {failure.To}: {failure.Error}");
}

#Credits & payments

Credits.cs
csharp
var balance = await client.Credits.BalanceAsync();
Console.WriteLine($"{balance.Balance} credits on account {balance.AccountId}");

var history = await client.Credits.HistoryAsync(page: 1, perPage: 50);
foreach (var tx in history)
{
    Console.WriteLine($"{tx.Type} of {tx.Amount} -> balance: {tx.BalanceAfter}");
}

// Mobile money top-up
var payment = await client.Payments.CreateAsync(
    amount: 50000,
    provider: "snippe",
    phone: "0712345678"
);
Console.WriteLine($"{payment.Id}: {payment.CreditAmount} credits");

#Webhooks

Webhooks.cs
csharp
// Inside your ASP.NET webhook endpoint:
var evt = client.Webhooks.Parse(
    requestBody,
    signature: Request.Headers["X-SendAfrica-Signature"]
);
// throws WebhookSignatureException on mismatch

if (evt.Type == "sms.delivered")
{
    Console.WriteLine($"Message {evt.MessageId} was delivered");
}

#Error handling

Errors.cs
csharp
try
{
    await client.Sms.SendAsync("0712345678", "Hello");
}
catch (InvalidPhoneException)
{
    Console.WriteLine("Please check the phone number");
}
catch (InsufficientCreditsException)
{
    Console.WriteLine("Not enough credits — top up first");
}
catch (RateLimitException e)
{
    Console.WriteLine($"Rate limited — retry after {e.RetryAfter}s");
}
catch (SendAfricaException e)
{
    Console.WriteLine($"API error: {e.Message} (status={e.StatusCode})");
}