Documentation menu
Ruby / SDK REFERENCE
Ruby SDK Guide
The official Ruby SDK for sending Kakao Alimtalk, Brand Message and SMS — standard library only, works standalone or with Rails.
이 문서의 목차
- 패키지
- sendgo
- 언어
- Ruby
- 레지스트리
- RubyGems
gem install sendgoThe official Ruby SDK for sending Kakao Alimtalk, Brand Message and SMS
sendgo is the official Ruby SDK for the Sendgo messaging API.
It uses only net/http and json from the standard library, and is the core behind the sendgo-rails extension.
Requires Ruby 3.1 or newer.
Install
gem install sendgo
Or in a Gemfile:
gem "sendgo"
Quick start
require "sendgo"
client = Sendgo::Client.new(
access_key: ENV.fetch("SENDGO_ACCESS_KEY"),
secret_key: ENV.fetch("SENDGO_SECRET_KEY"),
kakao_sender_key: ENV["SENDGO_KAKAO_SENDER_KEY"],
sms_sender_key: ENV["SENDGO_SMS_SENDER_KEY"],
api_version: "v2"
)
# Send an Alimtalk
client.alimtalk.send(
template_code: "ORDER_CONFIRM_001",
contacts: [
{ contact: "01012345678", name: "Gildong Hong", var1: "ORD-001", var2: "29,000 KRW" }
]
)
# Send an SMS
client.sms.send_sms(
content: "[Sendgo] Your code is 123456 (valid for 5 minutes)",
contacts: [{ contact: "01012345678" }]
)
Sendgo::Client.new raises ArgumentError when access_key or secret_key is missing, so a misconfigured client fails at construction rather than at the first send.
All methods take keyword arguments only.
Alimtalk in detail
# Multiple recipients
client.alimtalk.send(
template_code: "ORDER_CONFIRM_001",
contacts: [
{ contact: "01011111111", name: "Gildong Hong", var1: "ORD-001" },
{ contact: "01022222222", name: "Chulsoo Kim", var1: "ORD-002" }
]
)
# Scheduled send
client.alimtalk.send(
template_code: "PROMO_SUMMER_2026",
schedule_type: "SCHEDULED",
at: "2026-07-28 09:00:00",
contacts: [{ contact: "01012345678", var1: "Summer sale" }]
)
# Fall back to SMS when the Alimtalk fails
client.alimtalk.send(
template_code: "DELIVERY_START_001",
replace_sms: "Y",
sms_subject: "[Shipping notice]",
sms_content: "Your order has shipped.\nTracking: #{'#{var2}'}",
contacts: [{ contact: "01012345678", var1: "ORD-001", var2: "1234567890" }]
)
Template placeholders use the #{var2} form, which collides with Ruby string interpolation — put them in single-quoted strings, or escape as shown above.
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.
# Text
client.friendtalk.send(
content: "Hello! Check out this month's deals.",
contacts: [{ contact: "01012345678" }]
)
# Image
client.friendtalk.send(
message_type: "FI",
content: "This week's featured products.",
image_url: "https://cdn.example.com/banner.jpg",
image_link: "https://example.com/event",
contacts: [{ contact: "01012345678" }]
)
# With buttons
client.friendtalk.send(
content: "Your coupon has arrived. Use it now!",
buttons: [{ name: "Get coupon", type: "WL", linkMo: "https://example.com/coupon" }],
contacts: [{ 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
api_version: "v2".
# Single send — channel friends
client.brand_message.send(
targeting: "M",
message_type: "FL",
friend_template_uuid: "9cd5460b-6458-4edc-9b11-c26d3013c340",
contacts: [{ contact: "01012345678", var1: "29,000 KRW" }]
)
# Broadcast — every consenting channel friend (no contacts)
client.brand_message.broadcast(
message_type: "FW",
friend_template_uuid: "9cd5460b-6458-4edc-9b11-c26d3013c340"
)
# Campaign lookups
campaigns = client.brand_message.campaigns(from: "2026-08-01", count: 10)
one = client.brand_message.campaign("1f0a6d0e-6b3b-4f0f-9b2f-2f6f6a1b7c11")
broadcast drops contacts and forces targeting: "F" — an empty recipient array would be rejected as an invalid request.
The carousel payload argument is named list and is passed through unchanged.
SMS / LMS / MMS
# SMS (up to 90 bytes)
client.sms.send_sms(
content: "[Sendgo] Your code is 123456 (valid for 5 minutes)",
contacts: [{ contact: "01012345678" }]
)
# LMS (long text, up to 2,000 bytes)
client.sms.send_lms(
subject: "[Important] Scheduled maintenance",
content: "Maintenance: 2026-07-25 02:00–06:00",
contacts: [{ contact: "01012345678" }]
)
# MMS
client.sms.send_mms(
subject: "[Event] July deals",
content: "Check out this month's deals!",
contacts: [{ contact: "01012345678" }]
)
Rails
Use sendgo-rails, which builds a memoised client from config.sendgo with ENV fallbacks:
# config/application.rb
config.sendgo.access_key = ENV["SENDGO_ACCESS_KEY"]
config.sendgo.secret_key = ENV["SENDGO_SECRET_KEY"]
config.sendgo.kakao_sender_key = ENV["SENDGO_KAKAO_SENDER_KEY"]
config.sendgo.api_version = "v2"
Sendgo::Rails.client.alimtalk.send(
template_code: "ORDER_CONFIRM_001",
contacts: [{ contact: order.phone, var1: order.number }]
)
Sendgo::Rails.client returns the full core client, so brand_message, friendtalk and sms are all available on it. Call Sendgo::Rails.reset! in tests to drop the memoised instance.
Active Job
Sending is a network call, so it belongs in a job:
class SendOrderConfirmJob < ApplicationJob
retry_on Sendgo::SendgoError, wait: :polynomially_longer, attempts: 3
def perform(phone, order_no)
Sendgo::Rails.client.alimtalk.send(
template_code: "ORDER_CONFIRM_001",
contacts: [{ contact: phone, var1: order_no }]
)
rescue Sendgo::SendgoError => e
# A 4xx will not succeed on retry — fail immediately instead of burning attempts.
raise e if e.status_code >= 500
Rails.logger.error("Sendgo #{e.status_code} [#{e.error_code}]: #{e.message}")
end
end
Error handling
begin
client.alimtalk.send(
template_code: "ORDER_CONFIRM_001",
contacts: [{ contact: "01012345678" }]
)
rescue Sendgo::SendgoError => e
case e.error_code
when "INVALID_ACCESS_KEY", "INVALID_SECRET_KEY"
notify_ops("Check the Sendgo API keys.")
when "PAYMENT_REQUIRED"
notify_ops("Out of Sendgo credit.")
when "IP_NOT_ALLOWED"
notify_ops("IP is not allow-listed.")
when "INVALID_TEMPLATE_CODE"
logger.warn("Unknown template")
else
e.status_code >= 500 ? retry_later : logger.error("Sendgo #{e.status_code}: #{e.message}")
end
end
Branch on error_code, 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
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
access_key |
String |
required | — | Sendgo access key |
secret_key |
String |
required | — | Sendgo secret key |
kakao_sender_key |
String |
optional | nil |
Kakao sender profile key |
sms_sender_key |
String |
optional | nil |
SMS caller ID key |
api_version |
String |
optional | "v1" |
API version (v1 | v2) |
base_url |
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 = sendgo.short_url.create(
target_url: "https://example.com/promotions/summer-sale",
title: "Summer sale landing"
)
code = created.dig("data", "code")
link = created.dig("data", "shortUrl")
# Reaction stats — daily series + device / referrer / country breakdowns
stats = sendgo.short_url.stats(code, from: "2026-08-01")
sendgo.short_url.list(count: 10)
sendgo.short_url.show(code)
sendgo.short_url.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:
sendgo(RubyGems) - Repository: send-go/ruby
- Registry: https://rubygems.org/gems/sendgo
- 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 kakao_sender_key, 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.