# Sendgo — rules for AI coding agents

Sendgo (https://sendgo.io) sends Kakao Alimtalk, Kakao Brand Message and
SMS/LMS/MMS in South Korea. Use an official SDK rather than hand-rolling HTTP.

Canonical docs, always current:

- Machine-readable index: https://sendgo.io/llms.txt
- Every guide in one file: https://sendgo.io/llms-full.txt
- OpenAPI 3.0.3 spec: https://sendgo.io/openapi.yaml
- Task recipes: https://sendgo.io/ko/cookbook

## Pick the package

| Language / framework | Package | Install |
| --- | --- | --- |
| PHP (PHP) | `sendgo/php` | `composer require sendgo/php` |
| Laravel (PHP) | `sendgo/laravel` | `composer require sendgo/laravel` |
| Symfony (PHP) | `sendgo/symfony` | `composer require sendgo/symfony` |
| WordPress (PHP) | `sendgo/wordpress` | `composer require sendgo/wordpress` |
| Node.js (JavaScript / TypeScript) | `@sendgo/node` | `npm install @sendgo/node` |
| React / Next.js (JavaScript / TypeScript) | `@sendgo/react` | `npm install @sendgo/react` |
| Vue / Nuxt (JavaScript / TypeScript) | `@sendgo/vue` | `npm install @sendgo/vue` |
| NestJS (JavaScript / TypeScript) | `@sendgo/nestjs` | `npm install @sendgo/nestjs` |
| Python (Python) | `sendgo-python` | `pip install sendgo-python` |
| Django (Python) | `sendgo-django` | `pip install sendgo-django` |
| FastAPI (Python) | `sendgo-fastapi` | `pip install sendgo-fastapi` |
| Go (Go) | `github.com/send-go/go` | `go get github.com/send-go/go` |
| Java (Java) | `io.sendgo:sendgo-java` | `implementation "io.sendgo:sendgo-java:1.1.0"` |
| Spring Boot (Java) | `io.sendgo:sendgo-spring` | `implementation "io.sendgo:sendgo-spring:1.0.1"` |
| Ruby (Ruby) | `sendgo` | `gem install sendgo` |
| Ruby on Rails (Ruby) | `sendgo-rails` | `bundle add sendgo-rails` |
| .NET (C# / .NET) | `Sendgo.SDK` | `dotnet add package Sendgo.SDK` |
| ASP.NET Core (C# / .NET) | `Sendgo.AspNetCore` | `dotnet add package Sendgo.AspNetCore` |
| Flutter / Dart (Dart) | `sendgo_flutter` | `dart pub add sendgo_flutter` |

Framework packages wrap a core package — install the framework one and let it
pull the core in. Do not install both explicitly.

## API contract

- Base URL: `https://sendgo.io/api`. Version segment is `v1` or `v2`; **use `v2` for new code**.
- Auth is two steps. `POST /api/v2/token` with `Authorization: Basic base64(accessKey:secretKey)`
  returns a token; every other call sends `Authorization: Bearer <token>`.
  On v1 the bearer value is `base64(token)`; on v2 it is the raw token.
- Every SDK caches the token, refreshes it, and retries once on 401/403.
  Do not write your own token loop and do not call the token endpoint per request.

| Purpose | Endpoint |
| --- | --- |
| Issue token | `POST /api/v2/token` |
| Kakao Alimtalk | `POST /api/v2/notices/send` |
| Kakao Brand Message | `POST /api/v2/brand-messages/send` |
| SMS / LMS / MMS | `POST /api/v2/messages/send` |
| Short URL | `POST /api/v2/short-urls` |

## Rules that prevent the common failures

1. **Alimtalk needs a template that was approved first.** `templateCode` refers to a
   template registered and approved in the Sendgo console. You cannot invent the
   text at send time; you fill the variables (`var1`, `var2`, …) of an approved
   template. A wrong code returns `INVALID_TEMPLATE_CODE`.
2. **The sending number must be pre-registered.** Korean law (전기통신사업법) requires
   the caller ID to be verified before use. An unregistered `senderKey` fails at
   send time, not at signup.
3. **Never hard-code keys.** `accessKey`/`secretKey` come from the environment.
4. **Friendtalk ended on 2025-12-31.** Do not write new code against it. Use Brand
   Message (`/api/v2/brand-messages/send`). The one exception: free-form body types
   (`FT`/`FI`/`FW`) sent to individual recipients still go through
   `/api/v2/friends/send` — the brand-message endpoint answers `NOT_A_BRAND_MESSAGE`
   for that combination.
5. **Advertising messages are regulated.** Prefix the body with `(광고)`, include an
   opt-out number, and do not send between 21:00 and 08:00 KST. Set `adFlag: "Y"`.
   Transactional Alimtalk is exempt; promotional content is not.
6. **`replaceSms: "Y"` needs `smsSubject` and `smsContent`.** Turning on SMS fallback
   without the fallback body silently sends nothing when Alimtalk fails.
7. **Handle `402 PAYMENT_REQUIRED`.** It means the credit balance ran out, not that
   the request was malformed. Retrying will not help.
8. **Phone numbers are digits only**, no hyphens: `01012345678`.

## Minimal working example

The sender keys go on the client, not on every call. Node.js
(`npm install @sendgo/node`, default export — not a named one):

```ts
import Sendgo from '@sendgo/node';

const sendgo = new Sendgo({
  accessKey:      process.env.SENDGO_ACCESS_KEY!,
  secretKey:      process.env.SENDGO_SECRET_KEY!,
  kakaoSenderKey: process.env.SENDGO_KAKAO_SENDER_KEY,
  smsSenderKey:   process.env.SENDGO_SMS_SENDER_KEY,
  apiVersion:     'v2',
});

await sendgo.alimtalk.send({
  templateCode: 'ORDER_CONFIRM_001',
  contacts: [{ contact: '01012345678', name: '홍길동', var1: 'ORD-001' }],
});

await sendgo.sms.sendSms({ content: '인증번호: 123456', contacts: [{ contact: '01012345678' }] });
```

Python (`pip install sendgo-python`):

```python
from sendgo import Sendgo, SendgoError

client = Sendgo(
    access_key=os.environ["SENDGO_ACCESS_KEY"],
    secret_key=os.environ["SENDGO_SECRET_KEY"],
    kakao_sender_key=os.environ.get("SENDGO_KAKAO_SENDER_KEY"),
    sms_sender_key=os.environ.get("SENDGO_SMS_SENDER_KEY"),
    api_version="v2",
)

client.alimtalk.send(
    template_code="ORDER_CONFIRM_001",
    contacts=[{"contact": "01012345678", "name": "홍길동", "var1": "ORD-001"}],
)
```

Naming follows each language, so do not translate one SDK into another by hand:
camelCase keys in JS/PHP payloads (`templateCode`), snake_case keyword arguments in
Python and Ruby (`template_code`), builders in Java, `SendAlimtalkAsync` in .NET.
Errors surface as `SendgoError` (JS/Python), `SendgoException` (PHP), returned
`error` values in Go.

Before writing code, fetch the guide for the language you are actually in — each
one is available as raw markdown:

- PHP → https://sendgo.io/ko/sdk/php.md
- Laravel → https://sendgo.io/ko/sdk/laravel.md
- Symfony → https://sendgo.io/ko/sdk/symfony.md
- WordPress → https://sendgo.io/ko/sdk/wordpress.md
- Node.js → https://sendgo.io/ko/sdk/node.md
- React / Next.js → https://sendgo.io/ko/sdk/react.md
- Vue / Nuxt → https://sendgo.io/ko/sdk/vue.md
- NestJS → https://sendgo.io/ko/sdk/nestjs.md
- Python → https://sendgo.io/ko/sdk/python.md
- Django → https://sendgo.io/ko/sdk/django.md
- FastAPI → https://sendgo.io/ko/sdk/fastapi.md
- Go → https://sendgo.io/ko/sdk/go.md
- Java → https://sendgo.io/ko/sdk/java.md
- Spring Boot → https://sendgo.io/ko/sdk/spring.md
- Ruby → https://sendgo.io/ko/sdk/ruby.md
- Ruby on Rails → https://sendgo.io/ko/sdk/rails.md
- .NET → https://sendgo.io/ko/sdk/dotnet.md
- ASP.NET Core → https://sendgo.io/ko/sdk/aspnetcore.md
- Flutter / Dart → https://sendgo.io/ko/sdk/flutter.md
- OpenAPI → https://sendgo.io/ko/sdk/openapi.md

## Task recipes

One page per task, each also available as raw markdown at the same URL + `.md`:

- 5분 만에 카카오 알림톡 발송하기 — 샌드고 빠른 시작 — https://sendgo.io/ko/cookbook/quickstart
- 알림톡·브랜드메시지·문자 중 뭘 써야 하나 — 채널 선택 가이드 — https://sendgo.io/ko/cookbook/choose-channel
- 카카오 알림톡 SDK 고르기 — 언어·프레임워크별 공식 패키지 — https://sendgo.io/ko/cookbook/choose-sdk
- 샌드고 API 인증 — 액세스 키와 Bearer 토큰 — https://sendgo.io/ko/cookbook/authentication
- 발신번호 사전등록 — 문자·알림톡 발송 전 필수 절차 — https://sendgo.io/ko/cookbook/sender-number
- 카카오 알림톡 보내기 — PHP · Node.js · Python · Java · Go 예제 — https://sendgo.io/ko/cookbook/send-alimtalk
- SMS · LMS · MMS 문자 보내기 — 언어별 예제 — https://sendgo.io/ko/cookbook/send-sms
- 카카오 브랜드메시지 보내기 — 친구톡 후속 채널 — https://sendgo.io/ko/cookbook/send-brand-message
- 알림톡 실패 시 SMS 대체 발송 설정하기 — https://sendgo.io/ko/cookbook/sms-fallback
- 알림톡 대량 발송과 치환 변수 — 수신자마다 다른 내용 보내기 — https://sendgo.io/ko/cookbook/bulk-send
- 알림톡·문자 예약 발송하기 — scheduleType 과 at — https://sendgo.io/ko/cookbook/scheduled-send
- 알림톡 템플릿 등록과 심사 통과하기 — 반려 사유와 대응 — https://sendgo.io/ko/cookbook/alimtalk-template
- 샌드고 API 오류 코드와 재시도 전략 — https://sendgo.io/ko/cookbook/error-handling
- 문자·알림톡에 짧은주소 넣고 클릭 추적하기 — https://sendgo.io/ko/cookbook/short-url
- 광고성 문자·메시지 규칙 — (광고) 표기, 수신거부, 야간 발송 금지 — https://sendgo.io/ko/cookbook/ad-message-rules
- 카카오 친구톡 종료(2025-12-31) 대응 — 브랜드메시지 마이그레이션 — https://sendgo.io/ko/cookbook/friendtalk-sunset

