HaruMail ドキュメント

HaruMail は、日本のAI開発者のためのメール送受信APIです。独自ドメインからのトランザクションメール送信と、独自ドメインでのメール受信を、REST APIとMCPの2つの入口から使えます(cron・CI/CDはcurl 1行)。DNS設定(SPF / DKIM / DMARC)はすべてこちらで用意するので、渡されたAPIキーだけで今日から送れます。

REST API

Resendに近い書き味のJSON API。curl一発で送信。

MCP

Claude・Cursor等のAIエージェントから直接メールを送受信。

curl 1行

インストール不要。cron・CI/CDのスクリプトにそのまま足せます。

ベースURL: https://harumail.app(正式ドメインは後日切替予定。切替後も旧URLは動作します)

クイックスタート

APIキー(hm_ で始まる文字列)はオンボーディング時にお渡ししています。まず1通送ってみます。

curl -X POST https://harumail.app/v1/emails \
  -H "Authorization: Bearer hm_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "お店の名前 <info@example.com>",
    "to": "customer@example.jp",
    "subject": "ご予約ありがとうございます",
    "text": "このたびはご予約ありがとうございます。"
  }'
const res = await fetch("https://harumail.app/v1/emails", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.HARUMAIL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    from: "お店の名前 ",
    to: "customer@example.jp",
    subject: "ご予約ありがとうございます",
    text: "このたびはご予約ありがとうございます。",
  }),
});
const { id } = await res.json(); // em_xxxx
import os, requests

res = requests.post(
    "https://harumail.app/v1/emails",
    headers={"Authorization": f"Bearer {os.environ['HARUMAIL_API_KEY']}"},
    json={
        "from": "お店の名前 ",
        "to": "customer@example.jp",
        "subject": "ご予約ありがとうございます",
        "text": "このたびはご予約ありがとうございます。",
    },
)
print(res.json())  # {"id": "em_xxxx", ...}

成功すると {"id": "em_...", "status": "sent", ...} が返ります。届いたかどうかは送信履歴やダッシュボードでいつでも確認できます。

認証(APIキー)

すべてのAPIは Authorization: Bearer hm_... ヘッダーで認証します。キーはアカウント(テナント)単位で発行され、そのアカウントに登録された差出人ドメインからしか送信できません。キーが漏れても他社のドメインからは1通も送れない設計です。

APIキーはサーバーサイドで使ってください。ブラウザのコードに埋め込むと第三者に読まれます。キーの再発行・失効はサポートまで(即時対応します)。

レート制限: 120リクエスト/分(キー単位)。超えると 429 が返るので、少し待って再試行してください。

メールを1通送信します。

フィールド必須説明
fromstring必須差出人。"info@example.com" または "表示名 <info@example.com>"。登録済みドメインのアドレスに限る
tostring | string[]必須宛先。to/cc/bcc合計50件まで
subjectstring必須件名
textstringテキスト本文(htmlとどちらか必須)
htmlstringHTML本文。textとの併記推奨(届きやすさが上がります)
reply_tostring任意返信先アドレス
cc / bccstring | string[]任意CC / BCC
headersobject任意カスタムヘッダー(文字列→文字列)
attachmentsarray任意{filename, content(base64), content_type, disposition?, content_id?} の配列。32個まで・メール全体で5MiBまで
scheduled_atstring任意予約送信。"2026-08-20 09:00"(日本時間)またはISO8601。下の「予約送信」参照
tagsarray任意{name, value} の配列(最大10個)。送信履歴・イベント通知に載る突合用ラベル(ステップメールのシーケンスID等)
// レスポンス(200)
{
  "id": "em_1a2b3c4d5e6f7a8b9c0d",
  "status": "sent",
  "from": "お店の名前 <info@example.com>",
  "to": ["customer@example.jp"],
  "subject": "ご予約ありがとうございます",
  "message_id": "...",
  "created_at": "2026-08-06 12:34:56"
}

予約送信(1通ごとの日時指定・変更・キャンセル)

scheduled_at を付けると即時送信せず予約になります。レスポンスの id送信後も同じなので、予約中から配信後まで1つのidで追跡できます。

// レスポンス: { "id": "em_...", "status": "scheduled", "scheduled_at": "..." }

PATCH  /v1/emails/:id   {"scheduled_at": "..."}   // 日時変更(予約中のみ)
DELETE /v1/emails/:id                             // キャンセル(予約中のみ)
POST   /v1/emails/:id/cancel                      // DELETEと同じ(Resend互換の別名)
GET    /v1/emails?status=scheduled                // 予約中の一覧

ステップメールの組み方: 登録時にステップごとの scheduled_attags(例: {"name":"sequence","value":"welcome"}, {"name":"step","value":"3"})を付けて予約し、成約・配信停止したら残りの予約idをキャンセルするだけです。配信停止は suppression.added イベント(下の送信イベントWebhook)が合図になります。

添付ファイルの例

{
  "from": "info@example.com",
  "to": "customer@example.jp",
  "subject": "請求書をお送りします",
  "text": "請求書を添付いたします。",
  "attachments": [
    { "filename": "invoice.pdf", "content": "JVBERi0xLjQK...", "content_type": "application/pdf" }
  ]
}
POST/v1/emails/batch

一斉送信(メルマガ・お知らせ配信)。{"emails": [送信オブジェクト, ...]} の形式で1リクエスト最大100通。各通は独立に検証・送信・記録され、宛先ごとに本文を変えられます。結果は通ごとに返り、月間上限に達した時点で残りは送信されず明示されます。

{
  "emails": [
    { "from": "news@example.com", "to": "a@example.jp", "subject": "8月のお知らせ", "text": "A様 ..." },
    { "from": "news@example.com", "to": "b@example.jp", "subject": "8月のお知らせ", "text": "B様 ..." }
  ]
}
// レスポンス: { "data": [{index, id, status} | {index, error}], "sent": 2, "failed": 0 }
広告・宣伝を含む配信は、受信に同意した相手(オプトイン)にのみ送ってください(特定電子メール法)。同意のない広告メールの送信は利用規約で禁止しています。
POST/v1/emails/bulk

大量配信・予約送信・ステップメールのためのキュー投入。1リクエスト最大1,000通を受け付け、毎分100通ずつの安全な速度で自動配信します(ISPに嫌われにくいドリップ方式)。scheduled_atで日時指定("2026-08-10 09:00"は日本時間として解釈・各通ごとの個別指定も可)。

{
  "emails": [ { "from": "...", "to": "...", "subject": "...", "text": "..." }, ... ],
  "scheduled_at": "2026-08-10 09:00"
}
// レスポンス: { "batch_id": "bk_...", "queued": 1000, "scheduled_from": "..." }

進捗は GET /v1/bulk/:batch_id(queued/sent/failed件数・失敗理由・次回送信時刻)、未送信分の取り消しは DELETE /v1/bulk/:batch_idステップメールは、同じ宛先リストへ scheduled_at を「登録日・3日後・7日後」とずらして複数回投入するだけで組めます。

GET/v1/emails

送信履歴を新しい順に返します(本文なしの要約。delivery_status / opened_at / clicked_at つき)。クエリ: limit(1–200・既定20)、statussent / failed)、before(続きを取るカーソル。応答の next_before をそのまま渡す。無くなったら最後のページ)。

curl -H "Authorization: Bearer hm_..." \
  "https://harumail.app/v1/emails?limit=10&status=failed"

# 200通ずつ全部たどる
curl ... "https://harumail.app/v1/emails?limit=200"                      # → {"data":[...], "next_before":"2026-09-10 12:00:03|em_..."}
curl ... "https://harumail.app/v1/emails?limit=200&before=2026-09-10%2012:00:03%7Cem_..."   # 次のページ
GET/v1/emails/:id

送信メール1件の詳細を返します。本文(text / html)・エラー内容・添付のメタ情報を含みます。失敗調査はまずここを見てください。

冪等性(二重送信防止)

Idempotency-Key ヘッダーを付けると、同じキーでの再送信は実際には送信せず初回の結果をそのまま返します。リトライ処理やAIエージェントからの送信で二重送信を防げます。キーは注文IDなど自然な一意値を推奨(256文字まで・テナント内で一意)。

curl -X POST .../v1/emails \
  -H "Authorization: Bearer hm_..." \
  -H "Idempotency-Key: order-20260806-0012" \
  -d '{ ... }'
GET/v1/inbound

受信メールを新しい順に返します(要約)。GET /v1/inbound/:id で本文・ヘッダーを含む詳細が取れます。受信メールは90日間保持されます。

受信を使うには、対象ドメインの受信設定(MXレコード)をこちらで行います。オンボーディング時に「受信も使う」と伝えてください。既存のメール受信(Google Workspace等)と共存させる設計もご相談ください。

受信Webhook

メールを受信した瞬間に、登録されたURLへ通知をPOSTします(設定はサポートまで)。ペイロード:

{
  "type": "inbound.received",
  "data": { "id": "in_...", "from": "...", "to": "...", "subject": "...", "created_at": "..." }
}

本文は含まれないため、GET /v1/inbound/:id で取得してください。リクエストには署名ヘッダーが付きます:

x-harumail-signature: sha256=<HMAC-SHA256 hex>

// 検証(Node)
import { createHmac, timingSafeEqual } from "node:crypto";
const expected = "sha256=" + createHmac("sha256", WEBHOOK_SECRET).update(rawBody).digest("hex");
const valid = timingSafeEqual(Buffer.from(expected), Buffer.from(header));

送信イベントWebhook(opt-in)

送信・開封・クリックもWebhookで受け取れます(設定はサポートまで)。同じURL・同じ署名方式で、次のイベントが届きます:

{
  "id": "evt_...",
  "type": "email.sent" | "email.failed" | "email.opened" | "email.clicked" | "email.bounced"
        | "suppression.added" | "suppression.removed",
  "created_at": "2026-08-15T09:00:00.000Z",
  "data": { "email_id": "em_...", "from": "...", "to": ["addr@example.jp"], "subject": "...",
            "tags": [{"name":"sequence","value":"welcome"}] }   // email.* の形。tagsは指定時のみ
  // suppression.* の data: { "email": "addr@example.jp", "reason": "unsubscribe" | "manual" }
}
  • email.opened / email.clicked"track": true で送ったメールの初回開封・クリック時に1回ずつ届きます(クリックは開封も同時に確定)
  • email.failed には data.error が付きます
  • email.bounced は配送不能通知(DSN)を受けた時に届きます。恒久的失敗(hard)の宛先は自動で抑制リストに入ります(data.bounce に type / status / diagnostic)
  • suppression.added は配信停止リストに実際に追加された瞬間(ワンクリック解除・API・hardバウンス)に届きます。ステップメールの停止合図に使ってください
  • 配送は at-least-once: 失敗時は1分・5分・30分・120分後に自動再送します(計5回)。再送のボディは同一なので id で重複排除してください
  • 配送ログは GET /v1/events?type=...&status=pending|delivered|failed で確認できます(保存30日)。記録の正は GET /v1/emails/:id です

配信停止(ワンクリックunsubscribe)と抑制リスト

送信時に "unsubscribe": true を付けると(メルマガ・お知らせ・広告はこれを付けてください):

  • Gmailなどが対応するワンクリック配信停止ヘッダー(RFC 8058・Gmailの大量送信者要件)と、本文末尾の配信停止リンクを自動付与
  • 停止した宛先は自動で抑制リストに入り、以後の unsubscribe: true 送信からは自動除外(422で明示)
  • 取引メール(注文確認等・unsubscribeなしの送信)は止まりません(意図的な設計)

リストの確認・手動追加・解除: GET/POST /v1/suppressionsDELETE /v1/suppressions/:email。増減は suppression.added / suppression.removed イベント(送信イベントWebhook)でリアルタイムに受け取れます。

開封・クリック計測と統計

"track": true を付けたHTMLメールは開封(ピクセル)とクリック(署名付きリダイレクト・改ざん不可)を計測します。GET /v1/stats で直近30日の送信・失敗・受信・開封・クリック・開封率・配信停止数を取得。大量配信は GET /v1/bulk/:id にも開封・クリック数が出ます。

フェイルオーバー配信(Business以上・準備中)

この機能は現在準備中です(提供開始まで料金には含みません)。開始時に対象プランのお客様へご案内します。以下は提供予定の仕様です。

メールは「配信網」(送信インフラ)を通って届きますが、どの配信網もまれに障害を起こします。HaruMailは別会社の予備配信網を常時スタンバイし、主経路の障害・一時的なレート制限を検知すると、その1通から自動で予備網に切り替えて届け続けます。

  • お客様の設定・コード変更は一切不要(サービスの裏側で自動)
  • 差出人の認証設定(SPF/DKIM)は両方の網に対して当社が維持します
  • どちらの網で届いたかは送信履歴の provider/v1/statssent_via_failover に記録=「保険が働いた回数」まで見えます
  • 設定ミス起因のエラー(差出人未検証等)は切替対象外(切り替えても届かないため)
1社の配信基盤だけに依存しない「マルチプロバイダ配信」は、Resend・SendGrid等の単一基盤サービスにはない設計です。BusinessまたはProプランで自動的に有効になります。
GET/v1/domains

このAPIキーで差出人に使えるドメインの一覧を返します。ドメインの追加はサポートまで(SPF / DKIM / DMARC の設定込みでこちらが対応します。お客様側のDNS作業は原則不要です)。

GET/v1/usage
{ "month": "2026-08", "sent": 128, "failed": 2, "limit": 3000, "remaining": 2872,
  "upgrade_url": "https://harumail.app/?ref=tn_xxx-yyy#pricing" }

月間上限に達すると送信APIは 402 を返します(それまでの送信は影響を受けません)。402のメッセージと upgrade_urlプランと料金への導線が入っています。upgrade_url にはご自身のアカウントを示す署名付きの参照が入っていて、このURL(または harumail upgrade)からお支払いいただくと、決済がアカウントに自動で結び付いて上限が上がります。参照なしでお申し込みいただいた場合は、アカウントを確認のうえ担当者が反映します(1営業日以内)。

エラー

エラーはすべて {"error": "日本語の説明"} の形で返ります。

HTTP意味
400JSONの形式が不正
401APIキーが無効・失効
402月間送信上限に到達
403登録されていないドメインからの送信
404対象が見つからない
422フィールドの内容が不正(メッセージに具体的な理由)
429レート制限(120回/分)
502配信基盤側のエラー(メッセージに詳細。送信は記録され status: failed で履歴に残る)

MCPサーバー

HaruMail はMCP(Model Context Protocol)サーバーを標準提供しています。Claude等のAIエージェントに登録すると、AIが直接メールを送受信できるようになります。認証はREST APIと同じキーです。

claude mcp add --transport http harumail \
  https://harumail.app/mcp \
  --header "Authorization: Bearer hm_xxxxxxxxxxxxxxxx"

登録後はAIに「予約確認メールをcustomer@example.jpに送って」と話すだけです。Cursor・その他のStreamable HTTP対応クライアントでも同じURLで使えます。

MCPツール一覧

ツールできること
send_email下書き作成(この時点では送信されない)
send_batch_emails / send_bulk_emails複数・大量配信の下書き作成(〜100通 / 〜1,000通・予約・ステップメール)
confirm_send下書きの送信確定(あなたが「送信して」と明確に指示した時だけAIが呼べる)
discard_draft下書きの破棄(24時間確定されない下書きは自動破棄)
get_bulk_status / cancel_bulk大量配信の進捗確認・未送信分の取り消し
list_emails / get_email送信履歴・詳細(エラー調査)
list_inbound / get_inbound受信メールの一覧・本文取得
list_domains差出人に使えるドメインの確認
get_usage今月の送信数・残数
安全設計: AI経由の送信は必ず「下書き→あなたの確認→送信確定」の二段階です。AIが勝手にメールを送ることは構造的にできません(送信確定は専用ツールに分離されており、確認なしの呼び出しを禁止しています。確定されない下書きは24時間で自動破棄)。加えて、送信できるのは登録済みドメインからだけ・月間上限とレート制限もRESTと共通で効きます。

ターミナル・cron・CI/CDから使う

インストールは不要です。curl だけで動くので、サーバーのcronやCI/CDのスクリプトにそのまま1行足せます。

# 環境変数にキーを入れておく
export HARUMAIL_API_KEY=hm_xxxxxxxxxxxxxxxx

# 送信(バックアップ完了通知の例)
./backup.sh && curl -s -X POST https://harumail.app/v1/emails \
  -H "Authorization: Bearer $HARUMAIL_API_KEY" -H 'content-type: application/json' \
  -d "{\"from\":\"info@example.com\",\"to\":\"me@example.jp\",\"subject\":\"バックアップ完了\",\"text\":\"$(date) 正常終了\"}"

# 送信履歴・受信メール・使用量
curl -s https://harumail.app/v1/emails?limit=10 -H "Authorization: Bearer $HARUMAIL_API_KEY"
curl -s https://harumail.app/v1/inbound       -H "Authorization: Bearer $HARUMAIL_API_KEY"
curl -s https://harumail.app/v1/usage         -H "Authorization: Bearer $HARUMAIL_API_KEY"

本文をファイルから渡す場合は jq を使うと安全です: jq -n --arg t "$(cat body.txt)" '{from:"info@example.com",to:"me@example.jp",subject:"件名",text:$t}' | curl -s -X POST … -d @-

専用CLI(npm公開済み・依存ゼロ)

インストール不要で npx からそのまま使えます。curlと同じことが短く書けます。

# APIキーを保存(初回のみ)
npx harumail login hm_xxxxxxxxxxxxxxxx

# 送信(バックアップ完了通知の例。--text - でstdinから本文を読む)
./backup.sh && date | npx harumail send --to me@example.jp --subject "バックアップ完了" --text -

# 送信箱・受信箱・使用量
npx harumail logs 10
npx harumail inbound
npx harumail usage

# プランのアップグレード(料金ページを開く)
npx harumail upgrade

# メールを読みやすく表示(送信em_・受信in_どちらのIDでも可)
npx harumail read in_xxxxx

グローバルに入れる場合は npm install -g harumail。パッケージは npmjs.com/package/harumail にあります。CI/CDでは環境変数 HARUMAIL_API_KEY が設定ファイルより優先されます。

AIエージェント連携

AIにHaruMailを組み込ませる場合は、仕様全文を1ファイルにまとめた llms-full.txt をAIに渡してください。「このAPIでメール送信を実装して」だけで統合できます。llms.txt(索引)にも対応しています。

ドメインお預かり(ネームサーバー変更)の安全手順

独自ドメインで送るには、ドメインのDNS管理をこちらでお預かりします(お名前.com等の契約はそのまま・ドメイン移管ではありません。作業はネームサーバー欄の書き換え1回だけ)。「NS変更でサイトやメールが壊れないか」への答えを、隠さず全部書きます。

正直なリスク開示

DNSの仕様上、外部から全レコードを完全に列挙する方法は存在しません。つまりこちらが把握できなかった設定(申告されていないサブドメインや外部サービスの検証レコード等)は移行時に漏れる可能性がゼロではありません。リスクの正体はこれ1つで、以下の手順はすべてこれを潰すためにあります。

こちらがやること(4段階)

  1. 全量調査 — 証明書ログ(crt.sh)による隠れサブドメインの列挙+定番レコードの機械チェック+利用サービスのヒアリング
  2. 差分ゼロの証明 — 新旧のDNSに同じ質問を投げて全件照合し、差分ゼロのレポートをお渡しして、確認・承諾をいただいてから切替します
  3. 切替後の監視 — 24〜48時間、同じ照合を自動で回して監視します
  4. 即時ロールバック — 元のDNS設定は消えないため、ネームサーバーを書き戻すだけで切替前の状態に完全復帰できます

お客様にお願いすること

利用中のサービス(メール・サイト・予約システム・社内ツール等)の申告です。申告いただけなかった設定に起因する障害は責任範囲外となります(利用規約 第5条)。不安な場合は、NS変更なしで使えるtrial差出人(下記FAQ)から始めてください。

よくある質問

ドメイン設定が終わる前に試せますか?

試せます。アカウント発行時に t-xxxxxx@(共有ドメイン) 形式のtrial差出人をお渡しします。DNS設定もNS変更も一切不要で、その場からAPI・MCPの送信を試せます。独自ドメインに切り替えるときも、コードの変更は from を書き換えるだけです。

迷惑メールに入りませんか?

送信ドメインごとにSPF / DKIM / DMARCを正しく設定した上で送信します(設定はこちらが代行)。DKIM署名は差出人ドメインと一致(アライメント)するため、GmailのDMARCポリシー要件を満たします。

Google Workspace(Gmail)でメールを使っていますが併用できますか?

できます。HaruMailの送信設定はサブドメイン(cf-bounce.あなたのドメイン)だけを使うため、普段のメール受信(MXレコード)や送信には一切触れません。Google Workspaceでの送受信はそのまま、同じドメインからAPIメールも送れるようになります。実際にGoogle Workspace運用中のドメインで検証済みです。

Resendとの違いは?

書き味はほぼ同じで、日本語ドキュメント・日本語エラーメッセージ・DNS設定の代行・受信込み、の点が異なります。既存のResend実装からの移行は、エンドポイントとキーの差し替えでほぼ完了します。

SMTPは使えますか?

現在はREST APIとMCPのみです。SMTP接続が必要な場合はご相談ください。

送信上限を超えたら?

402 が返り、それ以上は送信されません。超過課金は一切発生しません(上限に達したら止まるだけ。90%/100%時点で通知します)。プラン変更で即日引き上げできます。

料金は?

Free ¥0(3,000通/月・2ドメイン・期限なし)/ Standard ¥1,480(10,000通)/ Business ¥2,680(50,000通・請求書払い可)/ Pro ¥4,480(100,000通)。全プランに受信・Webhook・MCP・CLI・DNS設定代行が含まれます。AI向けの料金表は /pricing.md

個人・フリーランスでも使えますか?

使えます(事業でのご利用が対象です。法人限定の制約はありません)。請求書払いが必要な場合はBusinessプラン以上で対応します。

変更履歴

日付内容
2026-08-15マーケ機能: 名簿(Audiences)・宛先(Contacts・カスタム属性)・テンプレート({{変数}}差し込み・版管理)・Broadcast(名簿宛て一斉配信・配信停止自動除外)
2026-08-15バウンス検知(DSN受信→bounced記録・hardは自動抑制・email.bouncedイベント)/ダッシュボードに配達品質タブ
2026-08-15予約送信(1通ごとの日時指定・変更・キャンセル)/tags/suppressionイベント/Webhook配送のat-least-once化(自動再送+配送ログAPI)/一斉送信の上限を100通に拡大
2026-08-15送信イベントWebhook(email.sent / failed / opened / clicked・opt-in)
2026-08-06初版公開(送信 / 受信 / MCP / 冪等性 / Webhook)