Bulk Alimtalk sending and per-recipient variables
Send one template to many recipients with different values each, in batches. Batch sizing, partial failures, queue patterns and the data hygiene that prevents most incidents.
POST /api/v2/notices/sendBulk sending is one template, many values. Each entry in contacts carries its own variables, so the same wording can deliver a different order number, amount or date to each person.
The basic shape
await sendgo.alimtalk.send({
templateCode: 'ORDER_CONFIRM_001',
contacts: [
{ contact: '01011111111', name: 'Hong Gildong', var1: 'ORD-001', var2: '29,000원' },
{ contact: '01022222222', name: 'Kim Chulsoo', var1: 'ORD-002', var2: '15,000원' },
{ contact: '01033333333', name: 'Lee Younghee', var1: 'ORD-003', var2: '52,000원' },
],
});
client.alimtalk.send(
template_code="ORDER_CONFIRM_001",
contacts=[
{"contact": "01011111111", "name": "Hong Gildong", "var1": "ORD-001"},
{"contact": "01022222222", "name": "Kim Chulsoo", "var1": "ORD-002"},
],
)
<?php
$sendgo->alimtalk->send([
'templateCode' => 'ORDER_CONFIRM_001',
'contacts' => [
['contact' => '01011111111', 'name' => 'Hong Gildong', 'var1' => 'ORD-001'],
['contact' => '01022222222', 'name' => 'Kim Chulsoo', 'var1' => 'ORD-002'],
],
]);
Batching
Ten thousand recipients in one request means a timeout tells you nothing about how far it got, and retrying is expensive. Split into a few hundred at a time.
Node.js
const BATCH = 500;
async function sendInBatches(recipients: Recipient[]) {
const failures: Recipient[] = [];
for (let i = 0; i < recipients.length; i += BATCH) {
const chunk = recipients.slice(i, i + BATCH);
try {
await sendgo.alimtalk.send({
templateCode: 'ORDER_CONFIRM_001',
contacts: chunk.map((r) => ({
contact: r.phone,
name: r.name,
var1: r.orderNo,
var2: r.amount,
})),
});
} catch (error) {
// One bad batch must not stop the rest.
console.error(`batch ${i / BATCH} failed`, error);
failures.push(...chunk);
}
}
return failures;
}
PHP · Laravel
<?php
use Illuminate\Support\Collection;
collect($recipients)->chunk(500)->each(function (Collection $chunk) use ($sendgo) {
try {
$sendgo->alimtalk->send([
'templateCode' => 'ORDER_CONFIRM_001',
'contacts' => $chunk->map(fn ($r) => [
'contact' => $r->phone,
'name' => $r->name,
'var1' => $r->order_no,
'var2' => number_format($r->amount).'원',
])->values()->all(),
]);
} catch (\Sendgo\Php\Exception\SendgoException $e) {
Log::error('batch send failed', ['message' => $e->getMessage()]);
}
});
Python
BATCH = 500
for i in range(0, len(recipients), BATCH):
chunk = recipients[i:i + BATCH]
try:
client.alimtalk.send(
template_code="ORDER_CONFIRM_001",
contacts=[{"contact": r.phone, "name": r.name, "var1": r.order_no} for r in chunk],
)
except SendgoError as e:
logger.error("batch send failed: %s", e)
Do it in a queue
Never run a bulk send inside a web request. The user waits, and a timeout leaves no way to resume from the middle.
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Sendgo\Php\Sendgo;
use Sendgo\Php\Exception\SendgoException;
class SendOrderAlimtalk implements ShouldQueue
{
use Queueable;
// Most send failures fail identically on retry. Do not loop forever.
public int $tries = 3;
public int $backoff = 30;
public function __construct(private array $contacts) {}
public function handle(Sendgo $sendgo): void
{
$sendgo->alimtalk->send([
'templateCode' => 'ORDER_CONFIRM_001',
'contacts' => $this->contacts,
]);
}
public function failed(SendgoException $e): void
{
// Recording the failed batch is what lets you resend just the failures.
FailedDispatch::create(['contacts' => $this->contacts, 'reason' => $e->getMessage()]);
}
}
Partial failures
A 200 response does not mean every recipient received it. Numbers can be dead, recipients blocked, people not on KakaoTalk.
- Do not resend the whole batch — everyone who succeeded gets it twice.
- Resend only the failures, or enable SMS fallback so they roll over to text automatically.
- Per-recipient outcomes are in the console's send history.
Easy to get wrong
- Normalise numbers first. Real databases contain
010-1234-5678,+821012345678and01012345678side by side. Strip hyphens and country codes down to digits. - Deduplicate. A repeated number sends twice and bills twice.
- Check the credit balance up front. Running out midway through 10,000 messages returns
PAYMENT_REQUIREDand the remainder fails wholesale. - Advertising content is subject to the night ban. Make sure a batch cannot run past 21:00 KST → Advertising message rules
Next
자주 묻는 질문
- How many recipients can one request take?
- The contacts array can hold many recipients in a single request. Very large requests are risky though — a timeout leaves you unsure how much was delivered — so batches of a few hundred are more stable.
- Can each recipient get different values?
- Yes. Every entry in contacts carries its own var1 to var8. Sending the same template with a different order number and amount per person is the normal use.
- What if only some recipients fail?
- A request can succeed while individual recipients fail — invalid numbers, blocked recipients. Check per-recipient results in the console and resend only the failures; resending the whole batch double-sends to everyone who succeeded.
- Can I run a bulk send inside a web request?
- Not advisable. The external call lands in your response time, and on timeout you cannot tell how far it got. Move it to a queue job.