콘텐츠로 이동

API 키 및 웹훅

Mail Merge는 개발자와 노코드 빌더를 위한 REST API와 아웃바운드 웹훅을 제공합니다. API 키를 사용하면 스크립트가 웹 앱과 동일한 작업을 수행할 수 있습니다. 계정을 읽고, 템플릿과 연락처를 나열하고, 캠페인을 보내고 수신자를 추적할 수 있습니다. 웹훅을 사용하면 Mail Merge가 캠페인이 완료되거나 수신자가 열기, 클릭, 회신, 반송 또는 구독 해제할 때 귀사의 엔드포인트를 호출하므로 CRM, 스프레드시트 또는 Slack 채널이 폴링 없이 동기화 상태를 유지합니다.

둘 다 웹 앱의 설정 → 개발자에 있으며 Professional 플랜의 일부입니다(가격 참조). 코드를 작성하는 대신 AI 어시스턴트와 Mail Merge를 통신하고 싶다면 MCP 서버를 대신 사용하세요. 모든 플랜에서 동일한 기능을 도구로 제공합니다.

  1. 설정 → 개발자 → API 키를 열고 키 생성을 클릭합니다.
  2. 사용할 위치(Zapier, CRM 동기화)에 따라 이름을 지정하여 나중에 올바른 키를 취소할 수 있습니다.
  3. 키를 복사합니다. 한 번만 표시됩니다. Mail Merge는 해시만 보관합니다. 잃어버리면 취소하고 새로 만드세요.

계정당 최대 10개의 키를 가질 수 있습니다. 키를 취소하면 해당 키로 만든 모든 요청이 즉시 실패하고 목록에서 행이 사라집니다.

카드에 표시된 기본 URL에 대해 모든 요청에서 키를 Bearer 토큰으로 보냅니다.

Terminal window
curl https://merge.email/api/v1/me \
-H "Authorization: Bearer mm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

키는 이를 생성한 계정으로 작동합니다. 서명된 세션과 정확히 같습니다. 동일한 Google 권한, 동일한 일일 할당량, 동일한 플랜 제한입니다. 별도의 “API 사용자”는 없습니다.

API는 웹 앱이 사용하는 것과 동일한 /v1 표면이므로 화면에서 할 수 있는 모든 작업에는 뒤에 엔드포인트가 있습니다. 통합이 가장 자주 사용하는 것들입니다.

호출기능
GET /v1/me계정: 플랜, 일일 할당량(최대, 사용, 남음), 시간대, 템플릿 메타데이터.
GET /v1/templates · GET /v1/templates/{templateId}저장된 템플릿. 본문은 템플릿당 로드됩니다.
GET /v1/contacts · POST /v1/contacts연락처 책(페이지 매김: limit / cursor → nextCursor).
POST /v1/campaignsGoogle Sheet에서 캠페인을 보내거나, 예약하거나, 자동화합니다. 본문은 캠페인 빌더가 게시하는 것과 동일합니다. 시트, 수신자 열, {{merge tags}}가 있는 제목 및 본문, 전송 옵션.
GET /v1/campaigns · GET /v1/campaigns/{campaignId}/recipients캠페인 및 각 수신자의 상태(전송됨, 읽음, 클릭됨, 회신됨, 반송됨, 구독 해제됨).
POST /v1/campaigns/{campaignId}/status실행 중인 캠페인을 일시 중지, 재개 또는 중지합니다.
POST /v1/recipients/verify이메일 검증기.

요청 및 응답 본문은 JSON입니다. 전체 타입 지정 표면은 서버에서 OpenAPI 문서로 생성됩니다. 클라이언트 생성기용 스키마가 필요하면 문의하세요.

실패는 하나의 봉투가 있는 실제 HTTP 상태입니다.

{ "error": { "code": "professional_plan_required", "message": "API access is a Professional plan feature" } }
상태code의미
401알 수 없거나 취소된 키, 또는 계정의 Google 액세스를 다시 연결해야 합니다.
403professional_plan_required키의 계정이 더 이상 Professional 플랜에 없습니다. 키는 다운그레이드 시 삭제되지 않습니다. 플랜이 복구되면 다시 작동합니다.
429rate_limited한 키에서 분당 600개 요청 초과. 1분 기다린 후 다시 시도하세요.
400 / 404 / 409bad_request, not_found, conflict, …요청 자체. 수정할 사항을 설명하는 메시지가 있습니다.

속도 제한은 각 API 서버 인스턴스의 키당 계산되므로 실제 한계는 “분당 약 600개”입니다. 이를 기준으로 설계하지 마세요.

  1. 설정 → 개발자 → 웹훅을 열고 웹훅 추가를 클릭합니다.
  2. HTTPS URL(일반 http://은 거부됨)을 입력하고 수신해야 할 이벤트를 선택합니다.
  3. 새 행에서 테스트 보내기를 클릭합니다. Mail Merge가 ping을 게시하고 토스트가 엔드포인트의 응답을 알려줍니다.

각 엔드포인트는 자체 서명 비밀(whsec_…)을 가져옵니다. 행에 복사 버튼과 함께 표시됩니다. 계정당 최대 5개의 엔드포인트를 가질 수 있습니다.

이벤트시기data
campaign.completed캠페인의 마지막 이메일이 처리되었습니다.campaignId, name, status: "completed", sentCount, campaignSize
campaign.paused · campaign.resumed · campaign.stopped캠페인을 일시 중지, 재개 또는 중지했습니다.campaignId, name, status(paused / active / stopped), sentCount
email.opened수신자가 이메일을 열었습니다. 캠페인당 처음 한 번만.campaignId, recipient, at
email.clicked수신자가 추적된 링크를 클릭했습니다. 모든 클릭.campaignId, recipient, at, url
email.replied전송된 스레드에서 회신이 감지되었습니다.campaignId, recipient, at
email.bounced반송이 감지되었습니다.campaignId, recipient, at
recipient.unsubscribed수신자가 구독 해제 링크를 사용했습니다. 캠페인당 처음 한 번만.campaignId, recipient, at, method

열기 및 클릭은 캠페인에 추적이 켜져 있어야 합니다. 회신 및 반송은 모든 전송된 캠페인 후에 따르는 회신 스캔에서 옵니다.

Mail Merge는 구독된 엔드포인트당 이벤트당 하나의 POST를 JSON 본문으로 보냅니다.

{
"id": "6f1c2d3e-…",
"event": "email.opened",
"createdAt": "2026-10-15T14:03:21.512Z",
"data": { "campaignId": "…", "recipient": "ada@example.com", "at": "2026-10-15T14:03:21.498Z" }
}

그리고 세 개의 헤더:

헤더값
X-MailMerge-Event이벤트 이름. 본문의 event와 동일합니다.
X-MailMerge-Delivery배달 ID. 본문의 id와 동일합니다. 중복을 무시하는 데 사용하세요.
X-MailMerge-Signaturesha256= 다음에 원본 본문의 16진수 HMAC-SHA256이 엔드포인트의 비밀로 키됩니다.

5초 내에 2xx로 응답하세요. 네트워크 오류 또는 5xx에서 Mail Merge는 2초 후 한 번 재시도합니다. 4xx는 최종 판정으로 간주되고 재시도되지 않습니다. 동일한 배달 ID가 재시도에서 전송됩니다. 연속 20번의 배달 실패 후 엔드포인트는 비활성화되고 행에 표시됩니다. 엔드포인트를 수정한 후 삭제하고 다시 추가하세요. 성공한 배달이 카운터를 재설정합니다.

이벤트는 최소 한 번 배달되며 순서는 보장되지 않습니다. 특히 열기는 버스트로 도착합니다(추적 픽셀을 렌더링하는 모든 메일 클라이언트). 핸들러를 X-MailMerge-Delivery 또는 (event, campaignId, recipient)에서 멱등성으로 만드세요.

페이로드를 신뢰하기 전에 항상 검증하세요. 원본 요청 본문(JSON 파싱 전 정확한 바이트)에 대해 HMAC을 계산하고 상수 시간에 비교하세요.

// Node.js (Express with `express.raw({ type: "application/json" })`)
import { createHmac, timingSafeEqual } from "node:crypto"
export function verifyMailMergeSignature(rawBody, signatureHeader, secret) {
const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex")
const a = Buffer.from(expected)
const b = Buffer.from(signatureHeader ?? "")
return a.length === b.length && timingSafeEqual(a, b)
}
app.post("/mailmerge", (req, res) => {
if (!verifyMailMergeSignature(req.body, req.get("X-MailMerge-Signature"), process.env.MAILMERGE_WEBHOOK_SECRET)) {
return res.status(401).end()
}
const payload = JSON.parse(req.body)
// … handle payload.event / payload.data
res.status(204).end()
})
# Python
import hashlib, hmac
def verify_mailmerge_signature(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header or "")

코드 불필요: Catch Hook(Zapier Webhooks by Zapier), Custom webhook(Make) 또는 Webhook 트리거 노드(n8n)를 생성하고, 제공하는 URL을 엔드포인트로 붙여넣고, 이벤트를 선택하고, 테스트 보내기를 클릭하여 도구가 페이로드를 샘플링할 수 있도록 하세요. data 필드는 다음 단계에서 매핑하는 변수가 됩니다(시트에 행 추가, CRM 연락처 업데이트, Slack에 게시). 이러한 도구는 기본적으로 서명을 검증하지 않습니다. 제공하는 URL은 추측 불가능하며 이것이 의존하는 보호입니다.

  • AI 에이전트(MCP). 어시스턴트가 스크립트 대신 Mail Merge를 구동해야 하는 경우.
  • 캠페인. 수신자 엔드포인트의 상태가 의미하는 바.
  • 가격. Professional 플랜에 포함된 내용.