Termii.SDK
0.5.0
dotnet add package Termii.SDK --version 0.5.0
NuGet\Install-Package Termii.SDK -Version 0.5.0
<PackageReference Include="Termii.SDK" Version="0.5.0" />
<PackageVersion Include="Termii.SDK" Version="0.5.0" />
<PackageReference Include="Termii.SDK" />
paket add Termii.SDK --version 0.5.0
#r "nuget: Termii.SDK, 0.5.0"
#:package Termii.SDK@0.5.0
#addin nuget:?package=Termii.SDK&version=0.5.0
#tool nuget:?package=Termii.SDK&version=0.5.0
Termii .NET SDK
A .NET SDK for the Termii messaging, sender ID, Number API, Token API, and Insights APIs.
Installation
Install from NuGet:
dotnet add package Termii.SDK
Then import the SDK namespace:
using Termii;
Compatibility
The SDK targets netstandard2.0 and net8.0.
- .NET Core 3.1 applications use the
netstandard2.0asset. - .NET 5, .NET 6, .NET 7, .NET 8, .NET 9, and .NET 10 applications can consume the package.
- Modern .NET applications use the most compatible asset NuGet selects for the application target.
Configuration
Create a client manually:
var client = new TermiiClient(new TermiiOptions
{
ApiKey = "your-termii-api-key"
});
The default base URL is https://api.ng.termii.com. Override it only when your Termii account or environment requires a different base URL:
var client = new TermiiClient(new TermiiOptions
{
ApiKey = "your-termii-api-key",
BaseUrl = new Uri("https://api.ng.termii.com"),
Timeout = TimeSpan.FromSeconds(30)
});
For ASP.NET Core applications, register TermiiClient with dependency injection:
builder.Services.AddTermii(options =>
{
options.ApiKey = builder.Configuration["Termii:ApiKey"]!;
});
Use it from a service or endpoint:
public sealed class NotificationService
{
private readonly TermiiClient _termii;
public NotificationService(TermiiClient termii)
{
_termii = termii;
}
public Task<TermiiMessageResponse> SendAsync(string phoneNumber, string message)
{
return _termii.Messaging.SendAsync(new SendMessageRequest
{
To = phoneNumber,
From = "Termii",
Sms = message,
Channel = TermiiMessageChannel.Generic,
Type = TermiiMessageType.Plain
});
}
}
Messaging
Send a single SMS:
var response = await client.Messaging.SendAsync(new SendMessageRequest
{
To = "2348012345678",
From = "Termii",
Sms = "Hello from .NET",
Channel = TermiiMessageChannel.Generic,
Type = TermiiMessageType.Plain
});
Send a bulk SMS:
var response = await client.Messaging.SendBulkAsync(new SendBulkMessageRequest
{
To = new[] { "2348012345678", "2348098765432" },
From = "Termii",
Sms = "Hello everyone",
Channel = TermiiMessageChannel.Generic,
Type = TermiiMessageType.Plain
});
Send through the Number API:
var response = await client.Numbers.SendAsync(new SendNumberMessageRequest
{
To = "2348012345678",
Sms = "Hello from a dedicated Termii number"
});
Send a WhatsApp template message:
var template = await client.Messaging.SendWhatsAppTemplateAsync(new SendWhatsAppTemplateRequest
{
PhoneNumber = "2348012345678",
DeviceId = "device-123",
TemplateId = "template-123",
Language = "en"
});
Sender IDs
Fetch sender IDs:
var senderIds = await client.SenderIds.GetAsync();
Request a sender ID:
var request = await client.SenderIds.RequestAsync(new RequestSenderIdRequest
{
SenderId = "Termii",
UseCase = "Transactional alerts",
Company = "Example Ltd"
});
Tokens and OTP
Send an OTP token:
var token = await client.Tokens.SendAsync(new SendTokenRequest
{
To = "2348012345678",
From = "Termii",
Channel = TermiiMessageChannel.Generic,
PinAttempts = 3,
PinTimeToLive = 10,
PinLength = 6,
PinPlaceholder = "< 123456 >",
MessageText = "Your verification code is < 123456 >"
});
Verify an OTP token:
var verification = await client.Tokens.VerifyAsync(new VerifyTokenRequest
{
PinId = token.PinId!,
Pin = "123456"
});
Generate an in-app OTP:
var generated = await client.Tokens.GenerateAsync(new GenerateTokenRequest
{
PhoneNumber = "2348012345678",
PinType = TermiiTokenPinType.Numeric,
PinAttempts = 3,
PinTimeToLive = 10,
PinLength = 6
});
The token client also supports voice OTP, voice call OTP, email OTP, and WhatsApp OTP through SendVoiceAsync, CallAsync, SendEmailAsync, and SendWhatsAppAsync.
Insights
Check account balance:
var balance = await client.Insights.GetBalanceAsync();
Check DND status:
var dnd = await client.Insights.CheckDndAsync(new CheckDndRequest
{
PhoneNumber = "2348012345678"
});
Query number intelligence:
var number = await client.Insights.QueryNumberAsync(new QueryNumberRequest
{
PhoneNumber = "2348012345678",
CountryCode = "NG"
});
Fetch message history:
var history = await client.Insights.GetMessageHistoryAsync(new GetMessageHistoryRequest
{
Page = 0,
Size = 15,
Sender = "Termii",
Receiver = "2348012345678"
});
Fetch message analytics:
var analytics = await client.Insights.GetMessageAnalyticsAsync(new GetMessageAnalyticsRequest
{
PhoneNumber = "2348012345678",
DateFrom = "2026-06-01",
DateTo = "2026-06-13"
});
Webhooks
Termii can send delivery/report callbacks to an endpoint you own. Verify the raw request body with the X-Termii-Signature header before trusting the payload:
app.MapPost("/webhooks/termii", async (HttpRequest request) =>
{
using var reader = new StreamReader(request.Body);
var payload = await reader.ReadToEndAsync();
var signature = request.Headers["X-Termii-Signature"].ToString();
if (!TermiiWebhookSignature.Verify(payload, signature, "your-webhook-secret"))
{
return Results.Unauthorized();
}
var webhookEvent = JsonSerializer.Deserialize<TermiiWebhookEvent>(payload);
if (webhookEvent.Status == "delivered")
{
Console.WriteLine($"Delivered message {webhookEvent.MessageId}");
}
return Results.Ok();
});
Webhook payloads can vary by event type and Termii account configuration. Unknown fields are preserved in TermiiWebhookEvent.AdditionalData.
Campaigns
Fetch campaign phonebooks:
var phonebooks = await client.Campaigns.GetPhonebooksAsync(new GetPhonebooksRequest
{
Page = 0,
Size = 15
});
Create a phonebook:
var phonebook = await client.Campaigns.CreatePhonebookAsync(new CreatePhonebookRequest
{
PhonebookName = "Customers",
Description = "Customer contacts"
});
Send a campaign to a phonebook:
var campaign = await client.Campaigns.SendAsync(new SendCampaignRequest
{
CountryCode = "234",
SenderId = "Termii",
Message = "Welcome to Termii.",
Channel = "generic",
MessageType = "Plain",
PhonebookId = "phonebook-123",
CampaignType = "regular",
ScheduleSmsStatus = "regular"
});
Fetch campaign history:
var history = await client.Campaigns.GetCampaignHistoryAsync("C714360330258");
Contacts
Add a single contact to a phonebook:
var contact = await client.Contacts.AddAsync("phonebook-123", new AddContactRequest
{
PhoneNumber = "8123696237",
CountryCode = "234",
EmailAddress = "person@example.com",
FirstName = "Ada",
LastName = "Lovelace"
});
Upload contacts from a CSV file:
await using var file = File.OpenRead("contacts.csv");
var upload = await client.Contacts.UploadAsync(new UploadContactsRequest
{
PhonebookId = "phonebook-123",
CountryCode = "234",
File = file,
FileName = "contacts.csv"
});
Product Emails
Send a product notification email:
var email = await client.Emails.SendProductEmailAsync(new SendProductEmailRequest
{
EmailAddress = "person@example.com",
TemplateId = "template-123",
Subject = "Order update"
});
Error Handling
The SDK throws TermiiApiException for non-success HTTP responses from Termii:
try
{
await client.Messaging.SendAsync(new SendMessageRequest
{
To = "2348012345678",
From = "Termii",
Sms = "Hello from .NET",
Channel = TermiiMessageChannel.Generic
});
}
catch (TermiiApiException ex)
{
Console.WriteLine($"HTTP status: {(int)ex.StatusCode}");
Console.WriteLine($"Termii code: {ex.TermiiCode}");
Console.WriteLine($"Termii message: {ex.TermiiMessage}");
}
Request models also validate required fields before sending. Missing required values throw ArgumentException, and invalid numeric ranges throw ArgumentOutOfRangeException.
Supported APIs
Implemented in the current SDK:
- Messaging: send single, WhatsApp conversational, and bulk messages.
- WhatsApp templates: send template messages with or without media.
- Sender IDs: list and request sender IDs.
- Number API: send message through a dedicated Termii number.
- Tokens: send, verify, generate, voice, email, and WhatsApp OTP flows.
- Insights: balance, DND status, number intelligence, message history, and message analytics.
- Campaigns: send campaigns, list campaigns, fetch campaign history, retry failed campaigns, and manage phonebooks.
- Contacts: list, add, upload, and delete phonebook contacts.
- Product emails: send template-based notification emails.
- Webhooks: delivery/report event models and HMAC SHA512 signature verification.
See docs/API_COVERAGE.md for the detailed coverage matrix.
Examples
Run the examples project after setting your Termii API key:
export TERMII_API_KEY="your-termii-api-key"
dotnet run --project examples/Termii.Examples
Run the offline webhook signature example:
export TERMII_EXAMPLE_ACTION="webhook-signature"
dotnet run --project examples/Termii.Examples
Run a live balance example:
export TERMII_API_KEY="your-termii-api-key"
export TERMII_EXAMPLE_ACTION="balance"
dotnet run --project examples/Termii.Examples
List phonebooks with a read-only live example:
export TERMII_API_KEY="your-termii-api-key"
export TERMII_EXAMPLE_ACTION="phonebooks-list"
dotnet run --project examples/Termii.Examples
List campaigns with a read-only live example:
export TERMII_API_KEY="your-termii-api-key"
export TERMII_EXAMPLE_ACTION="campaigns-list"
dotnet run --project examples/Termii.Examples
Send a live Number API example message:
export TERMII_API_KEY="your-termii-api-key"
export TERMII_EXAMPLE_ACTION="number-message"
export TERMII_EXAMPLE_PHONE_NUMBER="2348012345678"
dotnet run --project examples/Termii.Examples
Tests
Run the local test suite:
dotnet test
Integration tests are opt-in and must not call live Termii endpoints unless the required environment variables are present:
export TERMII_API_KEY="your-termii-api-key"
export TERMII_BASE_URL="https://api.ng.termii.com"
export TERMII_TEST_PHONE_NUMBER="2348012345678"
dotnet test tests/Termii.IntegrationTests
Release
Releases are published from version tags through GitHub Actions. See docs/RELEASING.md for the checklist.
Links
- Termii developer docs: https://developer.termii.com/
- NuGet package: https://www.nuget.org/packages/Termii.SDK
- API coverage: docs/API_COVERAGE.md
License
This project is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.Http (>= 8.0.1)
- System.Text.Json (>= 8.0.5)
-
net8.0
- Microsoft.Extensions.Http (>= 8.0.1)
- System.Text.Json (>= 8.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Add Contacts APIs, full Campaign APIs, webhook signature verification, and expanded examples.