文档菜单
A PRACTICAL GUIDE
Doing everything over the API — operations automation for resellers
Register Kakao channels, submit Alimtalk templates for review, file sender numbers, and sync opt-outs without ever sending anyone to sendgo.io. Includes webhook delivery of review outcomes.
이 문서의 목차
POST /api/v2/notice-templates이 가이드는 아직 번역되지 않아 English 문서를 표시합니다.
Sending has been an API from day one. Registration and review were not — attaching a Kakao channel, creating an Alimtalk template and submitting it, uploading sender number paperwork all meant someone logging into a console. For a business building a product on top of messaging that was the bottleneck: every new merchant meant "go over there, sign up, and register".
Not any more. Registration and review are API now. Your customers only see your screens.
What the API covers
| Task | Endpoint |
|---|---|
| Kakao channel verify / register / sync | /v2/kakao-senders |
| Alimtalk template CRUD, review, approval cancel | /v2/notice-templates |
| Brand message template CRUD | /v2/brand-templates |
| Kakao image upload | /v2/kakao-images/{type} |
| Sender number filing (all types) | /v2/senders |
| SMS snippet templates | /v2/message-templates |
| Opt-out (080) lookup | /v2/rejected-numbers |
| Event webhook subscription | /v2/webhook |
Exactly one step still involves a person, and it happens on your screen: the Kakao channel verification code. Kakao texts it to the channel administrator and Sendgo cannot see it either. Your user types it into your form.
Subscribe to webhooks first
Registration and review are asynchronous. Set up delivery before you start.
curl -X PUT "https://sendgo.io/api/v2/webhook" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://reseller.example.com/hooks/sendgo"}'
The secret in that response is shown once. Store it immediately.
Verify signatures against the raw bytes:
app.post('/hooks/sendgo', express.raw({ type: 'application/json' }), (req, res) => {
const expected = crypto
.createHmac('sha256', process.env.SENDGO_WEBHOOK_SECRET)
.update(req.body) // raw bytes, not a re-encoded object
.digest('hex');
if (expected !== req.get('X-Sendgo-Signature')) return res.sendStatus(401);
const { event, data, deliveryId } = JSON.parse(req.body.toString('utf8'));
// The same event can arrive twice — dedupe on deliveryId.
queue.add(event, { data, deliveryId });
res.sendStatus(204); // Process in a queue; slow handlers pile up retries.
});
Available events:
| Event | Fires when |
|---|---|
sender.status_changed |
Sender number approved or rejected |
notice_template.inspection_status_changed |
Alimtalk review result |
kakao_sender.status_changed |
Channel blocked or dormant |
kakao_sender.brand_message_status_changed |
Brand message M/N application result |
Use POST /v2/webhook/test to confirm the wiring first.
Registering a Kakao channel
Two calls.
# Step 1 — Kakao texts a verification code to the channel administrator
curl -X POST "https://sendgo.io/api/v2/kakao-senders/token" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"yellowId":"@my-channel","phoneNumber":"01012345678"}'
The response does not contain the code. Collect it on your screen, then:
# Step 2 — create the sender profile
curl -X POST "https://sendgo.io/api/v2/kakao-senders" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"token": "123456",
"yellowId": "@my-channel",
"phoneNumber": "01012345678",
"categoryCode": "001001"
}'
Look up categoryCode with GET /api/v2/kakao-senders/categories. The
kakaoSenderKey in the response is what every later Alimtalk and brand message
call uses.
The prerequisites match the console — the channel must exist on Kakao Business and be converted to a business channel.
Re-read channel status on a schedule
If Kakao blocks a channel, sending starts failing quietly.
curl -X POST "https://sendgo.io/api/v2/kakao-senders/sync" \
-H "Authorization: Bearer $TOKEN"
Run it daily from cron. Subscribing to kakao_sender.status_changed tells you
the moment it changes.
Filing a sender number
Start by asking what each type requires.
curl "https://sendgo.io/api/v2/senders/number-types" \
-H "Authorization: Bearer $TOKEN"
Every type can be filed over the API. For mobile types the console's PASS identity verification is replaced by an ID document that a Sendgo operator checks.
| Type | Identity check | Required documents |
|---|---|---|
personal_other (personal landline) |
none | usage certificate |
personal_mobile |
ID document | usage certificate + ID |
team_main (company landline / corporate phone) |
none | usage certificate |
team_representative_mobile |
ID document | usage certificate + ID |
team_emp_mobile |
ID document | usage certificate + ID + employment certificate |
team_other_company (delegated) |
none | usage certificate + 5 delegation documents |
curl -X POST "https://sendgo.io/api/v2/senders" \
-H "Authorization: Bearer $TOKEN" \
-F "senderAlias=Representative mobile" \
-F "senderNumberType=team_representative_mobile" \
-F "phoneE164=01012345678" \
-F "[email protected]" \
-F "[email protected]"
A filed number comes back PENDING. Numbers filed with documents are never
auto-approved — unlike the console's PASS path, which approves personal and
representative mobiles immediately. The result arrives as
sender.status_changed.
On rejection, rejectionReason carries the reason. Show it to the user, fix the
paperwork, file again.
Calling POST /api/v2/senders/validate first lets you report format and
duplicate problems back immediately.
Alimtalk templates and review
curl -X POST "https://sendgo.io/api/v2/notice-templates" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"kakaoSenderKey": "abc1234567890def",
"templateName": "Order received",
"templateContent": "#{name}, order #{orderNo} has been received.",
"templateMessageType": "BA",
"templateEmphasizeType": "NONE",
"categoryCode": "001001",
"messagePurpose": "order_delivery",
"legalBasis": "transaction",
"benefitOrigin": "none",
"expiryType": "none",
"optInReviewConfirmed": true,
"ctaClearConfirmed": true,
"policyConfirmed": true
}'
Those last seven fields are Sendgo's own policy gate, separate from Kakao's
review, and the API does not bypass them. Reasons come back in errors.reasons
and are safe to show the user verbatim. Wording that trips this gate is usually
rejected by Kakao too — being told instantly beats waiting days.
curl -X POST "https://sendgo.io/api/v2/notice-templates/TPL-20260911-0001/inspection" \
-H "Authorization: Bearer $TOKEN"
The outcome arrives as notice_template.inspection_status_changed. Without
webhooks, poll /sync.
created REG ← cannot send
submitted REQ ← under Kakao review (cancellable)
approved APR ← can send
rejected REJ ← read comments, fix, resubmit
In practice 30 minutes to one business day. Do not block a deployment pipeline on it.
Templates with images
A brand message imageUrl must be a Kakao-hosted URL. Upload first, then use
the URL you get back.
curl -X POST "https://sendgo.io/api/v2/kakao-images/default" \
-H "Authorization: Bearer $TOKEN" \
-F "[email protected]"
# → data.imageUrl
Alimtalk image templates take the file directly on the create call (multipart).
Syncing opt-outs
Advertising messages must not go to opted-out numbers. The send API filters them, but your own database needs the same state — otherwise you send and get filtered every time while your screen still says "subscribed".
curl "https://sendgo.io/api/v2/rejected-numbers?since=2026-09-01&count=500" \
-H "Authorization: Bearer $TOKEN"
Daily is enough.
An onboarding flow that never leaves your product
- Tell the merchant to open a Kakao business channel (your screen)
- Take channel id + admin phone →
POST /kakao-senders/token(automated) - Verification-code screen →
POST /kakao-senders(your screen + automated) - Document upload screen →
POST /senders(your screen + automated) - Bulk-create your standard template set with
POST /notice-templates(automated) - Submit each with
POST .../inspection(automated) - Receive approvals by webhook and notify the merchant (automated)
sendgo.io never appears in that list.
Next steps
- Registering an Alimtalk template and passing review — which wordings get rejected
- Sender numbers and sender profiles — the two kinds of key
- Error codes and retry strategy
자주 묻는 질문
- Can I complete the whole integration without sending customers to sendgo.io?
- Yes. Kakao channel registration, sender number filing, Alimtalk and brand message template creation and review submission, SMS snippets and opt-out lookup are all v2 API. Your customers only ever see your screens.
- Can mobile sender numbers be registered over the API?
- Yes. The console uses PASS identity verification; the API takes an ID document (identityDocument) and a Sendgo operator verifies it instead. Numbers filed this way are never auto-approved — they always start PENDING and wait for operator review.
- Can I register Alimtalk templates through the API?
- Yes. POST /api/v2/notice-templates creates it and POST /api/v2/notice-templates/{templateCode}/inspection submits it. Kakao performs the review, so the result is not immediate — subscribe to notice_template.inspection_status_changed or poll /sync.
- How do I receive review outcomes?
- Subscribe with PUT /api/v2/webhook. Sender approvals, Alimtalk review results, channel blocks and brand message targeting outcomes are pushed to you. Signatures are HMAC-SHA256 in the X-Sendgo-Signature header and must be verified against the raw request bytes.
- Is there anything a human still has to do?
- One thing: the Kakao channel verification code. Kakao texts it to the channel administrator and Sendgo never sees it. But the user types it into your screen, so nobody visits sendgo.io.
- What kind of account do I need?
- Kakao-related endpoints (channels, Alimtalk templates, brand message templates, image upload) require a team-owned application. Sender numbers, SMS templates, opt-outs and webhooks work with personal accounts too.
이 문서에서 쓰는 패키지
관련 문서
Registering an Alimtalk template and passing review →
How Kakao Alimtalk template review works, why informational-only matters, how to lay out variables, and the wordings that get rejected.
Sendgo API error codes and retry strategy →
Every error code returned by the Sendgo send endpoints, and how to tell a failure worth retrying from one that will fail identically every time.
Short links in SMS and Alimtalk, with click tracking →
Shorten long URLs to fit inside an SMS and measure who clicked. Creating short links, reading click stats, and splitting stats per campaign.