Chuyển tới nội dung chính

Chuyển từ Resend

Hạ Tầng Email theo API của Resend: cùng endpoint, cùng cấu trúc request và response, cùng dạng lỗi và cùng cách ký webhook. Phần lớn code chuyển sang được chỉ bằng cách đổi base URL và API key. Trang này liệt kê những gì tương thích, những gì khác, và các bước chuyển mà không mất thư.

Những gì tương thích​

Hạng mụcTương thích
Gửi emailPOST /emails với from, to, cc, bcc, reply_to, subject, html, text, headers, tags, attachments (dùng content), scheduled_at, template; POST /emails/batch; GET /emails/{id}; PATCH /emails/{id} để dời giờ; POST /emails/{id}/cancel.
IdempotencyHeader Idempotency-Key trên POST /emails.
LỗiBody { "statusCode", "name", "message" } và các tên như validation_error, restricted_api_key, rate_limit_exceeded, invalid_idempotent_request.
Tên miềnPOST /domains với name và custom_return_path, GET, PATCH (open_tracking, click_tracking, tls, capabilities.receiving), DELETE, POST /domains/{id}/verify.
API keyPOST /api-keys với permission (full_access hoặc sending_access) và domain_id.
WebhookQuản lý endpoint, tên sự kiện (email.sent, email.delivered, email.bounced, email.complained, email.opened, email.clicked, email.received, contact.*, domain.*…) và cấu trúc payload. Request được ký theo kiểu Svix, với header svix-id, svix-timestamp và svix-signature (cùng giá trị ở webhook-id, webhook-timestamp, webhook-signature), nên code xác minh hiện có vẫn chạy với secret whsec_… mới.
Contact/contacts, /segments, /topics, /contact-properties và API /audiences cũ.
Chiến dịch emailPOST /broadcasts với segment_id (hoặc audience_id), topic_id, /send với scheduled_at, /cancel.
Templates/templates, /publish, /duplicate, cú pháp {{{VAR}}} có giá trị mặc định tại chỗ, và {{{RESEND_UNSUBSCRIBE_URL}}}.
Automations/events, /events/send, /automations và các lượt chạy.
Nhận email/emails/receiving và tệp đính kèm.
Số liệuGET /emails/metrics.

Những gì khác​

Chủ đềResendHạ Tầng
Base URLhttps://api.resend.comhttps://api.hatang.dev
API keyre_…ht_…. Key Resend không dùng được. Key có phạm vi (email:send, email:write…); permission vẫn được nhận và chuyển thành phạm vi.
Tệp đính kèm theo URLpathChưa hỗ trợ: lỗi 422 invalid_attachment. Gửi content dạng base64.
Gửi theo lô/emails/batch không hỗ trợ Idempotency-Key. Lô không phải "tất cả hoặc không gì cả": các phần tử trước phần tử lỗi đã được gửi.
reactSDK renderGiống: SDK Node.js render bằng @react-email/render; API chỉ nhận html và text.
region của tên miềnChọn vùng gửiĐược nhận và lưu lại; việc gửi luôn dùng vùng Amazon SES của nền tảng.
Bản ghi DKIMresend._domainkeyrs<ngẫu nhiên>._domainkey, khoá mới cho mỗi tên miền.
Giới hạn tốc độTheo gói của Resend10 request mỗi giây cho mỗi doanh nghiệp.
SMTPsmtp.resend.com, nhiều cổng, user resendsmtp.hatang.dev:5870, chỉ STARTTLS, user hatang. Xem SMTP relay.
Danh sách chặnChỉ trong dashboard (Email → Danh sách nhận → Danh sách chặn), không có API.
Thêmtopic_id trên POST /emails, GET /emails/{id}/events có kết quả SMTP của từng người nhận, tìm kiếm và bộ lọc trên GET /emails, GET /logs và GET /usage.

Chuyển từng bước​

1. Thêm tên miền vào Hạ Tầng​

Thêm từng tên miền gửi ở Email → Tên miền và thêm các bản ghi mới bên cạnh bản ghi của Resend. Bản ghi DKIM dùng selector khác nên không xung đột.

Chọn return path khác khi cả hai cùng chạy

Resend và Hạ Tầng đều dùng send. làm tên miền phụ return path mặc định, mỗi bên có bản ghi MX nhận phản hồi Amazon SES riêng. Để không có hai bộ bản ghi thư trả lại trên cùng một tên, hãy chọn Return-Path tuỳ chỉnh khác trong Hạ Tầng (ví dụ hsend) khi thêm tên miền, hoặc gỡ bản ghi của Resend trước nếu bạn ngừng Resend cùng lúc.

Xác minh tên miền và chờ trạng thái Đã xác minh. Xem Tên miền.

2. Tạo API key​

Tạo một key cho mỗi hệ thống gửi email, chỉ với những phạm vi nó cần (email:send để gửi). Giới hạn key vào một tên miền nếu hệ thống đó chỉ nên gửi từ tên miền ấy.

3. Trỏ code sang Hạ Tầng​

Cách đơn giản nhất là chuyển sang @hatang/sdk, có cùng tên phương thức và cùng kết quả { data, error }:

// Trước
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({ from, to, subject, html });

// Sau
import { Hatang } from "@hatang/sdk";
const hatang = new Hatang(process.env.HATANG_API_KEY, { baseUrl: "https://api.hatang.dev" });
await hatang.emails.send({ from, to, subject, html });

Các lệnh tương ứng có trong emails, batch, domains, apiKeys, webhooks, audiences, contacts, segments, topics, contactProperties, broadcasts, templates, events và automations, và emails.send(payload, { idempotencyKey }) nhận cùng tuỳ chọn. Xem SDK Node.js.

Nếu gọi HTTP API trực tiếp, đổi base URL thành https://api.hatang.dev và key thành key ht_… của bạn. Không cần đổi gì khác.

4. Tạo lại webhook​

Tạo các endpoint webhook trong Hạ Tầng (mục Webhooks, hoặc POST /webhooks) với cùng các sự kiện, rồi đặt signing secret mới vào code xác minh. Xem Webhook.

5. Chuyển contact​

Xuất contact từ Resend và nhập CSV ở Email → Danh sách nhận (Nhập CSV), hoặc tạo bằng POST /contacts. Nhập những người đã huỷ đăng ký với unsubscribed là true để họ vẫn ở trạng thái huỷ đăng ký. Tạo lại topic và segment trước để gán contact vào.

6. Đổi thông tin SMTP​

Ứng dụng đang gửi qua SMTP của Resend cần host, cổng, tên đăng nhập và mật khẩu mới. Xem SMTP relay.

7. Theo dõi những ngày đầu​

Theo dõi Email → Số liệu và Email → Logs để thấy thư bị trả lại, báo spam và lệnh gọi lỗi. Khoá DKIM mới và return path mới chưa có lịch sử; hãy tăng dần các đợt gửi lớn như trong Khả năng vào hộp thư.

Chuyển từ SendGrid hoặc Postmark​

Hạ Tầng không có lớp tương thích cho các API này, nhưng request gửi thư của chúng ánh xạ từng trường sang POST /emails.

SendGrid (v3 Mail Send)​

SendGridHạ Tầng POST /emails
from.email, from.namefrom: "Tên <email>"
personalizations[].to, .cc, .bccto, cc, bcc. Một personalization là một email; nhiều personalization thì dùng POST /emails/batch.
personalizations[].dynamic_template_datatemplate.variables
template_idtemplate.id (id hoặc alias của template trên Hạ Tầng)
subjectsubject
content[] với text/plain và text/htmltext và html
reply_toreply_to
headersheaders
categories, custom_argstags (cặp name và value)
attachments[].content, .filename, .type, .content_idattachments[].content, .filename, .content_type, .content_id
send_at (Unix timestamp)scheduled_at (ISO 8601)

Postmark (/email)​

PostmarkHạ Tầng POST /emails
Fromfrom
To, Cc, Bcc (cách nhau bởi dấu phẩy)to, cc, bcc (mảng)
Subjectsubject
HtmlBody, TextBodyhtml, text
ReplyToreply_to
Headers ([{ "Name", "Value" }])headers ({ "Name": "Value" })
Tag, Metadatatags
Attachments[].Name, .Content, .ContentType, .ContentIDattachments[].filename, .content, .content_type, .content_id
TemplateAlias, TemplateModel (/email/withTemplate)template.id, template.variables
TrackOpens, TrackLinksTheo tên miền: open_tracking, click_tracking. Xem Theo dõi mở và nhấp.

Sự kiện webhook của hai dịch vụ này tương ứng với email.delivered, email.bounced, email.complained, email.opened và email.clicked của Hạ Tầng. Webhook của Hạ Tầng được ký bằng header kiểu Svix; xem Webhook.

Bước tiếp theo​

Xem trang này dạng Markdown