Sending
Every channel goes through a single unified send (omni). When you pass several messages, the next message is sent as a fallback if the previous one fails. The example below sends AlimTalk first and falls back to SMS if it fails.
To create a client and set up your API Key, see Install.
Unified send and fallback
import io.github.icommapi.bizgo.SendOptions;
import io.github.icommapi.bizgo.models.*;
SendResult result = client.send().omni(
List.of(Destination.builder().to("01000000000").replaceWords(Map.of("name", "Hong Gildong")).build()), // up to 200 recipients
List.of(
AlimtalkMessage.builder().senderKey("SENDER_KEY_EXAMPLE").templateCode("TEMPLATE_CODE_EXAMPLE")
.msgType("AT").text("Hi #{name}, your order has been received.").build(),
SmsMessage.builder().from("01000000000").text("Hi #{name}, your order has been received.").build()), // if AlimTalk fails
SendOptions.builder()
.idempotencyKey("order-20260923-0001") // retries never send twice
.ref("order-20260923-0001") // echoed back in reports
.build());
Message models by channel
Model names are the same in every SDK (Go writes acronyms in capitals, such as SMSMessage). Field names match the API (senderKey, from); Python also accepts snake_case such as sender_key (from is a reserved word, so it is from_).
| Channel | Model | Convenience method |
|---|---|---|
| SMS (90 bytes) | SmsMessage | sms |
| LMS (2,000 bytes) | MmsMessage (no fileKey) | lms |
| MMS | MmsMessage (up to 3 fileKeys) | mms |
| International SMS | InternationalMessage | |
| RCS | RcsMessage | |
| Kakao AlimTalk | AlimtalkMessage | |
| Kakao brand message | BrandMessage | |
| Naver TalkTalk | NaverTalkMessage |
SMS, LMS, and MMS can be sent with a convenience method that takes just the recipient and text. See Install for an example.
Validation before sending
The SDK checks each request before sending it. If something is wrong, it raises a validation error without calling the server. Errors contain only the field path and the reason, never input values such as phone numbers.
- Required fields, fields the model does not have (typos), allowed values, and the 200-recipient limit.
- Byte length (SMS 90 bytes, LMS 2,000 bytes, and so on, in EUC-KR) and characters outside EUC-KR (emoji).
- Conditionally required fields that become required depending on another field. AlimTalk needs different fields depending on how you send it.
| AlimTalk send type | Required values |
|---|---|
Full-text send (no sendType) | msgType (AT text, AI image) and text. The server rejects a missing value with A523, so the SDK stops it first. Use the msgType from the template lookup as is. |
Template substitution (sendType: template) | Send only senderKey and templateCode; every recipient needs replaceWords. |
Preventing duplicate sends (idempotencyKey)
With an idempotencyKey, sending again with the same key never delivers twice. We recommend setting it so you can safely retry after network errors.
- Bizgo requires
idempotencyTtl(0–86400 seconds) together with the key (A309 without it). If you omit the TTL, the SDK fills in 86400 seconds (24 hours). A value you set yourself (including 0) is sent as is, and no TTL is sent without a key. - Recipients already accepted with the same key are returned in
duplicates(A301) and are not sent again.
Reading the send result
The send result is an acceptance result. Get the final delivery outcome from reports.
| Result | Meaning |
|---|---|
msgKeys | Accepted message keys. Use them with reports and single lookups. |
failed | Recipients rejected at acceptance (empty if none) |
duplicates | Recipients already accepted with the same idempotencyKey (A301, not sent again) |
The names per language are Java getMsgKeys(), Python msg_keys, Go MsgKeys(), PHP msgKeys(), and C# MsgKeys.
Image messages (MMS)
Upload the image first to get a fileKey, then send it as MMS. MMS images must be jpg, up to 300 KB; larger files fail before sending. RCS and brand message images are uploaded the same way.
FileUploadResult uploaded = client.files().uploadMms(Path.of("banner.jpg"));
client.send().mms("01000000000", "01000000000", "Image notice", List.of(uploaded.getFileKey()));
client.files().uploadRcs(Path.of("card.png")); // -> getMedia()
client.files().uploadBrandMessage(Path.of("wide.jpg"), BrandImageKind.WIDE); // -> getImgUrl()
Files are read once and the same bytes are reused on retries. Uploads are retried only on HTTP 429.