Documentation menu
C# / .NET / SDK REFERENCE
.NET SDK Guide
The official .NET SDK for sending Kakao Alimtalk, Brand Message and SMS — async-first, nullable-enabled, records for every request.
이 문서의 목차
- 패키지
- Sendgo.SDK
- 언어
- C# / .NET
- 레지스트리
- NuGet
dotnet add package Sendgo.SDKThe official .NET SDK for sending Kakao Alimtalk, Brand Message and SMS
Sendgo.SDK is the official .NET SDK for the Sendgo messaging API.
Every method is async, nullable reference types are enabled, and requests are record types so payloads are immutable and easy to copy with with.
Targets .NET 8.0.
Install
dotnet add package Sendgo.SDK
Quick start
using Sendgo;
using Sendgo.Models;
var client = new SendgoClient(new SendgoOptions
{
AccessKey = Environment.GetEnvironmentVariable("SENDGO_ACCESS_KEY")!,
SecretKey = Environment.GetEnvironmentVariable("SENDGO_SECRET_KEY")!,
KakaoSenderKey = Environment.GetEnvironmentVariable("SENDGO_KAKAO_SENDER_KEY"),
SmsSenderKey = Environment.GetEnvironmentVariable("SENDGO_SMS_SENDER_KEY"),
ApiVersion = "v2",
});
// Send an Alimtalk
await client.SendAlimtalkAsync(new AlimtalkRequest
{
TemplateCode = "ORDER_CONFIRM_001",
Contacts = new[]
{
new Contact { PhoneNumber = "01012345678", Name = "Gildong Hong", Var1 = "ORD-001" },
},
});
Note that Contact.PhoneNumber serialises as contact in the request — the property is named for C# readability while the wire format stays unchanged.
AccessKey and SecretKey are required, so a missing key is a compile-time error rather than a runtime surprise.
Alimtalk in detail
// Multiple recipients
await client.SendAlimtalkAsync(new AlimtalkRequest
{
TemplateCode = "ORDER_CONFIRM_001",
Contacts = new[]
{
new Contact { PhoneNumber = "01011111111", Name = "Gildong Hong", Var1 = "ORD-001" },
new Contact { PhoneNumber = "01022222222", Name = "Chulsoo Kim", Var1 = "ORD-002" },
},
});
// Scheduled send
await client.SendAlimtalkAsync(new AlimtalkRequest
{
TemplateCode = "PROMO_SUMMER_2026",
ScheduleType = "SCHEDULED",
At = "2026-07-28 09:00:00",
Contacts = new[] { new Contact { PhoneNumber = "01012345678", Var1 = "Summer sale" } },
});
// Fall back to SMS when the Alimtalk fails
await client.SendAlimtalkAsync(new AlimtalkRequest
{
TemplateCode = "DELIVERY_START_001",
ReplaceSms = "Y",
SmsSubject = "[Shipping notice]",
SmsContent = "Your order has shipped.",
Contacts = new[] { new Contact { PhoneNumber = "01012345678", Var1 = "ORD-001" } },
});
Because requests are records, a shared base payload can be varied per send:
var baseRequest = new AlimtalkRequest { TemplateCode = "ORDER_CONFIRM_001", Contacts = Array.Empty<Contact>() };
await client.SendAlimtalkAsync(baseRequest with { Contacts = batchOne });
await client.SendAlimtalkAsync(baseRequest with { Contacts = batchTwo });
Friendtalk
⚠️ Deprecated — Friendtalk was discontinued on 2025-12-31 under Kakao's policy. Since 2026-01-01, Friendtalk send requests are automatically delivered as Brand Message (free-form) by Kakao. Calls still succeed, and this is still the only path for free-form types (
FT/FI/FW) sent to individual recipients, so there is no need to change working code right now.Use Brand Message instead for:
- template-based rich types (
FL/FC/FM/FP/FA)- recipients who are not channel friends (
targeting=N/I)- broadcasts to every opted-in channel friend (
targeting=F)Message types map one-to-one and the server does the conversion —
FT→BT,FI→BI,FW→BW,FL→BL,FC→BC,FM→BM,FP→BP,FA→BA.
await client.SendFriendtalkAsync(new
{
messageType = "FI",
content = "This week's featured products.",
imageUrl = "https://cdn.example.com/banner.jpg",
imageLink = "https://example.com/event",
contacts = new[] { new { contact = "01012345678" } },
});
SendFriendtalkAsync accepts object, so anonymous types work for the many optional Friendtalk shapes.
Brand Message
Brand Message is the successor channel to Friendtalk. Message types map one-to-one
(FT→BT, FI→BI, FW→BW, FL→BL, FC→BC, FM→BM, FP→BP, FA→BA);
pass the Friendtalk code and the server converts it.
Unlike Friendtalk it can also reach recipients who are not channel friends (Targeting = "N") and broadcast to every consenting channel friend (Targeting = "F").
v2 only. Set
ApiVersion = "v2".
// Single send — channel friends
await client.SendBrandMessageAsync(new BrandMessageRequest
{
Targeting = "M",
MessageType = "FL",
FriendTemplateUuid = "9cd5460b-6458-4edc-9b11-c26d3013c340",
Contacts = new[] { new Contact { PhoneNumber = "01012345678", Var1 = "29,000 KRW" } },
});
// Broadcast — every consenting channel friend (Contacts is dropped)
await client.BroadcastBrandMessageAsync(new BrandMessageRequest
{
MessageType = "FW",
FriendTemplateUuid = "9cd5460b-6458-4edc-9b11-c26d3013c340",
});
// Campaign lookups
var list = await client.GetBrandMessagesAsync(count: 10);
var one = await client.GetBrandMessageAsync("1f0a6d0e-6b3b-4f0f-9b2f-2f6f6a1b7c11");
BroadcastBrandMessageAsync applies with { Targeting = "F", Contacts = null } and the serialiser omits null properties, so a broadcast never sends an empty recipient array — which the API would reject.
SMS / LMS / MMS
// SMS (up to 90 bytes)
await client.SendSmsAsync(new SmsRequest
{
Content = "[Sendgo] Your code is 123456 (valid for 5 minutes)",
Contacts = new[] { new Contact { PhoneNumber = "01012345678" } },
});
// LMS (long text, up to 2,000 bytes)
await client.SendLmsAsync(new SmsRequest
{
Subject = "[Important] Scheduled maintenance",
Content = "Maintenance: 2026-07-25 02:00–06:00",
Contacts = new[] { new Contact { PhoneNumber = "01012345678" } },
});
// MMS
await client.SendMmsAsync(new SmsRequest
{
Subject = "[Event] July deals",
Content = "Check out this month's deals!",
Contacts = new[] { new Contact { PhoneNumber = "01012345678" } },
});
SendSmsAsync, SendLmsAsync and SendMmsAsync all take the same SmsRequest and set MessageType for you.
ASP.NET Core
Use Sendgo.AspNetCore, which registers SendgoClient as a singleton:
// Program.cs
builder.Services.AddSendgo(builder.Configuration.GetSection("Sendgo"));
// or configure inline
builder.Services.AddSendgo(options =>
{
options.AccessKey = builder.Configuration["Sendgo:AccessKey"]!;
options.SecretKey = builder.Configuration["Sendgo:SecretKey"]!;
options.KakaoSenderKey = builder.Configuration["Sendgo:KakaoSenderKey"];
options.ApiVersion = "v2";
});
// appsettings.json
{
"Sendgo": {
"AccessKey": "your_access_key",
"SecretKey": "your_secret_key",
"KakaoSenderKey": "your_kakao_sender_key",
"ApiVersion": "v2"
}
}
public class OrderNotifier(SendgoClient sendgo)
{
public Task ConfirmedAsync(string phone, string orderNo, CancellationToken ct = default) =>
sendgo.SendAlimtalkAsync(new AlimtalkRequest
{
TemplateCode = "ORDER_CONFIRM_001",
Contacts = new[] { new Contact { PhoneNumber = phone, Var1 = orderNo } },
}, ct);
}
Every send method takes a CancellationToken, so requests are cancelled with the HTTP request they belong to.
Error handling
using Sendgo.Exceptions;
try
{
await client.SendAlimtalkAsync(request, ct);
}
catch (SendgoException e)
{
switch (e.ErrorCode)
{
case "INVALID_ACCESS_KEY":
case "INVALID_SECRET_KEY":
logger.LogCritical("Check the Sendgo API keys");
break;
case "PAYMENT_REQUIRED":
logger.LogCritical("Out of Sendgo credit");
break;
case "IP_NOT_ALLOWED":
logger.LogCritical("IP is not allow-listed");
break;
case "INVALID_TEMPLATE_CODE":
logger.LogWarning("Unknown template");
break;
default:
if (e.StatusCode >= 500)
await retryQueue.EnqueueAsync(request, ct); // transient
else
logger.LogError("Sendgo {Status}: {Message}", e.StatusCode, e.Message);
break;
}
}
Branch on ErrorCode, not on the message text — messages can change, codes are the contract.
TOKEN_EXPIRED and TOKEN_MISMATCH are handled inside the SDK: the token is reissued and the request retried once.
Configuration options
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
AccessKey |
string |
required | — | Sendgo access key |
SecretKey |
string |
required | — | Sendgo secret key |
KakaoSenderKey |
string? |
optional | null |
Kakao sender profile key |
SmsSenderKey |
string? |
optional | null |
SMS caller ID key |
ApiVersion |
string |
optional | "v1" |
API version (v1 | v2) |
BaseUrl |
string |
optional | "https://sendgo.io" |
API base URL |
Short URL
Short URLs shrink the links in your message body and count whether they were actually clicked. SMS is billed by byte, so a shorter link leaves more room for copy.
v2 only.
Shortening the same target URL again returns the existing link. Pass forceNew
to mint a new code when you want per-campaign reaction figures kept separate.
deactivate does not delete the link — it only stops the redirect. Use it when a link
in an already-sent message has to be killed; the accumulated stats stay, and visitors
to a stopped link get 410 Gone.
var created = await sendgo.CreateShortUrlAsync(new ShortUrlRequest
{
TargetUrl = "https://example.com/promotions/summer-sale",
Title = "Summer sale landing",
}, ct);
// Reaction stats — daily series + device / referrer / country breakdowns
var stats = await sendgo.GetShortUrlStatsAsync(code, from: "2026-08-01", ct: ct);
await sendgo.GetShortUrlsAsync(count: 10, ct: ct);
await sendgo.GetShortUrlAsync(code, ct);
await sendgo.DeactivateShortUrlAsync(code, ct); // Stops the redirect only; the stats stay
stats returns a daily series (daily) plus breakdowns by device (byDevice), referrer (byReferer) and country (byCountry). The daily series is read from a pre-aggregated table, so response time stays flat no matter how many clicks accumulate.
Package information
- Package:
Sendgo.SDK(NuGet) - Repository: send-go/dotnet
- Registry: https://www.nuget.org/packages/Sendgo.SDK
- License: MIT
Getting your API keys
Sign in to Sendgo and open API/SDK → API integration to issue an access key and secret key.
Register a Kakao sender profile under Kakao channel to get your KakaoSenderKey, and a caller ID under Sender numbers for SMS.
이 패키지로 할 수 있는 것
Send a Kakao Alimtalk — PHP, Node.js, Python, Java, Go examples →
Send Kakao Alimtalk with an approved template code. Runnable code for Laravel, Node.js, Python, PHP, Java, Go, Ruby and .NET, plus every required field and why sends fail.
Send SMS, LMS and MMS in South Korea — code examples →
Send Korean SMS (90 bytes), LMS (long text) and MMS (with images) through Sendgo. Type selection, byte counting, verification-code patterns and advertising rules.