콘텐츠로 이동

브로드캐스트

브로드캐스트는 오디언스의 구독 중인 모든 연락처에게 메시지 한 통을 보냅니다. SpacePost는 이를 연락처마다 개인화된 이메일 한 통씩으로 나누고, 수신 거부 링크와 List-Unsubscribe 헤더를 추가하고, 발송 제외된 주소를 건너뛰며, 다른 이메일과 똑같이 모든 것을 추적합니다.

상태 의미
draft 생성되었으며 편집할 수 있고 발송되지 않았습니다.
queued send가 호출되어 시작 시각(즉시 또는 scheduled_at)을 기다리는 중입니다.
sending 연락처별로 분할해 발송하는 중입니다.
sent 모든 이메일이 전달을 위해 접수되었습니다. sent_at이 설정됩니다.
failed 분할 발송이 중단되었습니다. 예를 들어 할당량에 도달했거나 팀이 일시 중지된 경우입니다.
canceled 발송 전에 취소되었습니다.
broadcast.ts
import { SpacePost } from "@spacepost/node";
const spacepost = new SpacePost(process.env.SPACEPOST_API_KEY);
const audienceId = "0192e1c4-0000-7000-8000-0000000000a1";
// 1. Create a draft
const { data: draft, error } = await spacepost.broadcasts.create({
audienceId,
name: "October newsletter",
from: "Acme <news@acme.com>",
replyTo: "support@acme.com",
subject: "What's new at Acme, {{{FIRST_NAME|friend}}}",
previewText: "Three things we shipped this month",
html: `
<h1>Hi {{{FIRST_NAME|there}}},</h1>
<p>Here is what is new.</p>
<p><a href="{{{SPACEPOST_UNSUBSCRIBE_URL}}}">Unsubscribe</a></p>
`,
});
if (error) throw new Error(error.message);
// 2. Send it now, or schedule it
const { error: sendError } = await spacepost.broadcasts.send(draft.id, { scheduledAt: "in 1 hour" });
if (sendError) throw new Error(sendError.message);
// 3. Check progress
const { data: broadcast } = await spacepost.broadcasts.get(draft.id);
console.log(broadcast?.status); // "queued" | "sending" | "sent" | "failed"

POST /broadcasts는 초안을 만들고 { "id": "..." }를 반환합니다.

audience_idstring (uuid)필수

발송할 오디언스.

fromstring필수

확인된 도메인의 발신자.

subjectstring필수

1자 이상 998자 이하. 플레이스홀더를 사용할 수 있습니다.

htmlstring선택

HTML 본문. 발송하기 전에 html, text 또는 둘 다 제공하세요.

textstring선택

일반 텍스트 본문.

reply_tostring | string[]선택

최대 50개 주소.

preview_textstring선택

최대 200자. 받은편지함에서 제목 뒤에 표시되며, 숨겨진 프리헤더로 삽입됩니다.

namestring선택

최대 100자. 내부용 라벨.

PATCH /broadcasts/{id}는 같은 필드(모두 선택 사항)를 받으며 초안에서만 동작합니다. DELETE /broadcasts/{id}는 초안과 미래로 예약된 브로드캐스트에서 동작합니다.

터미널 창
# now
curl -X POST https://api.spacepost.dev/broadcasts/$ID/send -H "Authorization: Bearer $SPACEPOST_API_KEY"
# scheduled (ISO or natural language, up to 30 days ahead)
curl -X POST https://api.spacepost.dev/broadcasts/$ID/send \
-H "Authorization: Bearer $SPACEPOST_API_KEY" -H "Content-Type: application/json" \
-d '{ "scheduled_at": "2026-11-01T09:00:00Z" }'

html 또는 text 본문이 있는 초안만, 확인된 도메인에서 발송할 수 있습니다. 응답은 { "id": "..." }입니다.

발송하기 전에 GET /broadcasts/{id}/readiness가 전달률 체크리스트를 반환합니다(대시보드 편집기에도 같은 목록이 표시됩니다). SpacePost의 확장 기능이며 Resend API에는 없습니다.

{ "ready": true, "checks": [{ "id": "html_size", "level": "warn", "title": "Gmail will clip this message", "detail": "..." }] }
점검 수준 조건
sender_domain error from 도메인이 없거나 확인되지 않았습니다.
dmarc warn _dmarc.<domain>에 v=DMARC1 레코드가 없거나 조회에 실패했습니다. p=none은 통과합니다.
subject error / warn 비어 있으면 error입니다. 전부 대문자, !!!, $$$가 있거나 90자를 넘으면 warning입니다.
html_size warn HTML이 102 KB를 넘어 Gmail이 잘라 냅니다.
images warn 이미지만 있거나, 텍스트는 거의 없이 이미지가 네 개 이상입니다.
shorteners warn bit.ly, tinyurl.com, t.co 등을 거치는 링크입니다.
spam_phrases warn 제목이나 본문에 흔한 스팸성 문구가 있습니다.
unsubscribe ok 본문에 플레이스홀더가 없으면 수신 거부 푸터가 자동으로 추가되므로 발송이 차단되지 않습니다.
audience error 구독 중인 연락처가 없습니다.
role_addresses warn 연락처의 20% 넘게 info@나 admin@ 같은 주소입니다.

수준이 error인 점검이 하나라도 있으면 ready는 false입니다. 이때 발송하면 고쳐야 할 항목을 나열한 validation_error(422)로 실패합니다. warning은 발송을 막지 않습니다.

브로드캐스트 이메일에는 Gmail Postmaster Tools가 스팸 신고를 브로드캐스트에 귀속시킬 수 있도록 List-Id와 Feedback-ID 헤더(<broadcast id>:<team id>:broadcast:spacepost)도 포함됩니다. 트랜잭션 이메일에는 포함되지 않습니다.

  • 개인화는 subject, html, text에 적용됩니다(개인화).
  • 수신 거부: 본문에 {{{SPACEPOST_UNSUBSCRIBE_URL}}} / {{{RESEND_UNSUBSCRIBE_URL}}} 플레이스홀더가 없으면 수신 거부 푸터가 자동으로 덧붙여집니다. List-Unsubscribe와 List-Unsubscribe-Post: List-Unsubscribe=One-Click 헤더는 항상 추가됩니다.
  • 미리보기 텍스트는 HTML 맨 위의 숨겨진 프리헤더가 됩니다.
  • 수신 거부한 연락처와 발송 제외 목록에 있는 주소는 건너뜁니다.

수신자마다 요금제 할당량에서 이메일 한 통으로 계산되며, 신규 계정에는 하루 100통의 샌드박스 제한이 적용됩니다. 발송 도중 할당량이 소진되면 브로드캐스트는 failed로 끝나지만, 이미 생성된 이메일은 그대로 전달됩니다. 워커가 재시작해도 분할 발송은 이어서 진행됩니다.

브로드캐스트의 각 이메일은 일반 이메일입니다. GET /emails에 나타나고, 웹훅 페이로드에 broadcast_id가 포함되며, 반송되거나 열람될 수 있습니다.