Documentation menu
Go / SDK REFERENCE
Go SDK Guide
The official Go SDK for sending Kakao Alimtalk, Brand Message and SMS — standard library only, no third-party dependencies.
이 문서의 목차
- 패키지
- github.com/send-go/go
- 언어
- Go
- 레지스트리
- Go Modules
go get github.com/send-go/goThe official Go SDK for sending Kakao Alimtalk, Brand Message and SMS
github.com/send-go/go is the official Go SDK for the Sendgo messaging API.
It uses only the standard library — no third-party dependencies.
Install
go get github.com/send-go/go
import "github.com/send-go/go/sendgo"
Quick start
package main
import (
"log"
"os"
"github.com/send-go/go/sendgo"
)
func main() {
client, err := sendgo.New(sendgo.Config{
AccessKey: os.Getenv("SENDGO_ACCESS_KEY"),
SecretKey: os.Getenv("SENDGO_SECRET_KEY"),
KakaoSenderKey: os.Getenv("SENDGO_KAKAO_SENDER_KEY"),
SmsSenderKey: os.Getenv("SENDGO_SMS_SENDER_KEY"),
APIVersion: "v2",
})
if err != nil {
log.Fatal(err)
}
// Send an Alimtalk
err = client.Alimtalk.Send(sendgo.AlimtalkRequest{
TemplateCode: "ORDER_CONFIRM_001",
Contacts: []sendgo.Contact{
{Contact: "01012345678", Name: "Gildong Hong", Var1: "ORD-001", Var2: "29,000 KRW"},
},
})
if err != nil {
log.Fatal(err)
}
}
sendgo.New returns an error when the required keys are missing, so configuration mistakes surface at startup rather than at the first send.
Alimtalk in detail
// Multiple recipients
err = client.Alimtalk.Send(sendgo.AlimtalkRequest{
TemplateCode: "ORDER_CONFIRM_001",
Contacts: []sendgo.Contact{
{Contact: "01011111111", Name: "Gildong Hong", Var1: "ORD-001"},
{Contact: "01022222222", Name: "Chulsoo Kim", Var1: "ORD-002"},
},
})
// Scheduled send — `At` is a *string so "unset" and "empty" stay distinct
at := "2026-07-28 09:00:00"
err = client.Alimtalk.Send(sendgo.AlimtalkRequest{
TemplateCode: "PROMO_SUMMER_2026",
ScheduleType: "SCHEDULED",
At: &at,
Contacts: []sendgo.Contact{{Contact: "01012345678", Var1: "Summer sale"}},
})
For template variables beyond Var1–Var8, Contact also carries an arbitrary map:
{Contact: "01012345678", Variables: map[string]string{"title": "Order", "date": "2026-08-10"}}
Contact implements a custom MarshalJSON that flattens Variables into the request body, so named variables and the numbered Var* fields can be mixed freely.
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.
imageURL := "https://cdn.example.com/banner.jpg"
err = client.Friendtalk.Send(sendgo.FriendtalkRequest{
MessageType: "FI",
Content: "This week's featured products.",
ImageURL: &imageURL,
Contacts: []sendgo.Contact{{Contact: "01012345678"}},
})
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. Unlike the other channels this returns the
// response body, because you need the campaignId to poll results.
resp, err := client.BrandMessage.Send(sendgo.BrandMessageRequest{
Targeting: "M",
MessageType: "FL",
FriendTemplateUUID: "9cd5460b-6458-4edc-9b11-c26d3013c340",
Contacts: []sendgo.Contact{
{Contact: "01012345678", Var1: "29,000 KRW"},
},
})
// Broadcast — every consenting channel friend (Contacts is dropped)
resp, err = client.BrandMessage.Broadcast(sendgo.BrandMessageRequest{
MessageType: "FW",
FriendTemplateUUID: "9cd5460b-6458-4edc-9b11-c26d3013c340",
})
// Campaign lookups
list, err := client.BrandMessage.Campaigns(sendgo.BrandMessageListQuery{Count: 10})
one, err := client.BrandMessage.Campaign("1f0a6d0e-6b3b-4f0f-9b2f-2f6f6a1b7c11")
Broadcast clears Contacts before sending. The field is tagged omitempty, so a broadcast request omits the key entirely rather than sending an empty array, which the API would reject.
SMS / LMS / MMS
// SMS (up to 90 bytes)
err = client.SMS.SendSMS(sendgo.SmsRequest{
Content: "[Sendgo] Your code is 123456 (valid for 5 minutes)",
Contacts: []sendgo.Contact{{Contact: "01012345678"}},
})
// LMS (long text)
subject := "[Important] Scheduled maintenance"
err = client.SMS.SendLMS(sendgo.SmsRequest{
Subject: &subject,
Content: "Maintenance: 2026-07-25 02:00–06:00",
Contacts: []sendgo.Contact{{Contact: "01012345678"}},
})
Error handling
import "errors"
err := client.Alimtalk.Send(req)
if err != nil {
var sendgoErr *sendgo.SendgoError
if errors.As(err, &sendgoErr) {
switch sendgoErr.ErrorCode {
case "INVALID_ACCESS_KEY", "INVALID_SECRET_KEY":
log.Printf("check the Sendgo API keys")
case "PAYMENT_REQUIRED":
log.Printf("out of Sendgo credit")
case "IP_NOT_ALLOWED":
log.Printf("IP is not allow-listed")
default:
if sendgoErr.StatusCode >= 500 {
// transient — safe to retry with backoff
return retryLater(req)
}
log.Printf("sendgo %d: %s", sendgoErr.StatusCode, sendgoErr.Message)
}
return err
}
// network-level failure: the request may or may not have been accepted
return err
}
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.
A send endpoint that returns an error has not accepted the request, so 4xx/5xx responses are safe to retry without duplicate delivery. A network timeout is different — check the campaign list before retrying.
Concurrency
*Client is safe for concurrent use. The token manager serialises refreshes, so sharing one client across goroutines will not issue duplicate tokens. Create it once at startup and pass it around.
Configuration options
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
AccessKey |
string |
required | — | Sendgo access key |
SecretKey |
string |
required | — | Sendgo secret key |
KakaoSenderKey |
string |
optional | "" |
Kakao sender profile key |
SmsSenderKey |
string |
optional | "" |
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.
created, err := client.ShortURL.Create(sendgo.ShortURLRequest{
TargetURL: "https://example.com/promotions/summer-sale",
Title: "Summer sale landing",
})
if err != nil {
log.Fatal(err)
}
data := created["data"].(map[string]any)
code := data["code"].(string)
// Reaction stats — daily series + device / referrer / country breakdowns
stats, err := client.ShortURL.Stats(code, sendgo.ShortURLStatsQuery{From: "2026-08-01"})
client.ShortURL.List(sendgo.ShortURLListQuery{Count: 10})
client.ShortURL.Show(code)
client.ShortURL.Deactivate(code) // 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:
github.com/send-go/go(Go Modules) - Repository: send-go/go
- Reference: https://pkg.go.dev/github.com/send-go/go
- 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 your first Kakao Alimtalk in 5 minutes →
From issuing an access key to sending a Kakao Alimtalk, with working code in Node.js, Python, PHP, Laravel, Java and Go.
Sendgo API authentication — access keys and bearer tokens →
Exchange an accessKey and secretKey for a bearer token, and call the Sendgo API with it. Differences between v1 and v2, token caching, and the 401/403 codes.
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.