기업회원 신청 서류 안내
신청자 구분에 따라 재직증명서 또는 위임장을 함께 제출해 주세요.
신청자 구분에 따라 재직증명서 또는 위임장을 함께 제출해 주세요.
A PRACTICAL GUIDE
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.
이 가이드는 아직 번역되지 않아 English 문서를 표시합니다.
Most Sendgo errors are not fixed by retrying. The request is wrong, or the account is. Getting that distinction right is what keeps you from burning credit in a retry loop.
{
"code": "INVALID_TEMPLATE_CODE",
"message": "존재하지 않는 템플릿 코드입니다."
}
Validation failures carry per-field detail:
{
"code": "VALIDATION_FAILED",
"message": "The given data was invalid.",
"errors": {
"targetUrl": ["The target url field must be a valid URL."]
}
}
| HTTP | Code | Meaning | Retry |
|---|---|---|---|
| 400 | EMPTY_CONTACTS |
Recipient array is empty | ❌ |
| 400 | INVALID_TEMPLATE_CODE |
Unknown or unapproved template | ❌ |
| 400 | VALIDATION_FAILED |
Input validation failed | ❌ |
| 400 | NOT_A_BRAND_MESSAGE |
Free-form type sent to the brand-message endpoint | ❌ |
| 401 | INVALID_ACCESS_KEY |
Wrong access key or secret | ❌ |
| 402 | PAYMENT_REQUIRED |
Out of credit | ❌ (top up) |
| 403 | ACCESS_KEY_NOT_APPROVED |
App not approved | ❌ |
| 403 | IP_NOT_ALLOWED |
Called from outside the allowlist | ❌ |
| 404 | NOT_FOUND |
Campaign or resource missing | ❌ |
| 404 | INVALID_KAKAO_SENDER_KEY |
Wrong Kakao sender profile key | ❌ |
| — | Timeout / 5xx | Transient | ✅ |
Only the last row deserves a retry.
import Sendgo, { SendgoError } from '@sendgo/node';
try {
await sendgo.alimtalk.send({ templateCode: 'ORDER_CONFIRM_001', contacts });
} catch (error) {
if (error instanceof SendgoError) {
switch (error.code) {
case 'PAYMENT_REQUIRED':
await notifyOps('Sendgo credit exhausted');
break;
case 'INVALID_TEMPLATE_CODE':
case 'INVALID_KAKAO_SENDER_KEY':
// Configuration error — the deployed code is wrong. Make it loud.
logger.error('Sendgo misconfiguration', { code: error.code });
break;
default:
logger.warn('Alimtalk send failed', { code: error.code, message: error.message });
}
return; // do not retry
}
throw error; // network-level problems go to the caller's retry logic
}
from sendgo import SendgoError
NON_RETRYABLE = {
"EMPTY_CONTACTS", "INVALID_TEMPLATE_CODE", "VALIDATION_FAILED",
"INVALID_ACCESS_KEY", "PAYMENT_REQUIRED",
"ACCESS_KEY_NOT_APPROVED", "IP_NOT_ALLOWED", "INVALID_KAKAO_SENDER_KEY",
}
try:
client.alimtalk.send(template_code="ORDER_CONFIRM_001", contacts=contacts)
except SendgoError as e:
if e.code in NON_RETRYABLE:
logger.error("Alimtalk send failed, not retryable: %s", e.code)
return
raise
<?php
use Sendgo\Php\Exception\SendgoException;
try {
$sendgo->alimtalk->send([
'templateCode' => config('sendgo.templates.order_confirm'),
'contacts' => $contacts,
]);
} catch (SendgoException $e) {
Log::error('Alimtalk send failed', [
'code' => $e->getCode(),
'message' => $e->getMessage(),
'order' => $order->id,
]);
}
Keep the retry count low. Framework defaults will happily send the same doomed request dozens of times.
<?php
class SendAlimtalk implements ShouldQueue
{
public int $tries = 3;
public int $backoff = 30;
}
PAYMENT_REQUIRED is the dangerous one: with 10,000 jobs queued and a zero balance, default retry settings turn into tens of thousands of failing calls.
HTTP 200 means the request was accepted.
Per-recipient outcomes are in the console's send history.
<?php
// Normalise numbers, strip country codes, drop duplicates before sending.
$contacts = collect($recipients)
->map(fn ($r) => preg_replace('/\D/', '', $r->phone))
->map(fn ($p) => str_starts_with($p, '82') ? '0'.substr($p, 2) : $p)
->unique() // duplicates send twice and bill twice
->filter(fn ($p) => strlen($p) >= 10)
->values();
How Kakao Alimtalk template review works, why informational-only matters, how to lay out variables, and the wordings that get rejected.
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.
Shorten long URLs to fit inside an SMS and measure who clicked. Creating short links, reading click stats, and splitting stats per campaign.