Giới hạn tần suất
REST API giới hạn số request mà một doanh nghiệp gọi được mỗi giây, tính riêng cho từng module; riêng Email còn có hạn mức gửi hằng ngày. Trang này liệt kê các giới hạn, các header cho biết bạn đang ở đâu, và cách thử lại khi chạm giới hạn.
Số request mỗi giây
Giới hạn được đếm theo doanh nghiệp (không theo API key), trong cửa sổ trượt một giây. Mọi key của một doanh nghiệp dùng chung một hạn mức.
| Endpoint | Giới hạn |
|---|---|
Hỗ trợ, Sản phẩm và CRM: mọi thứ dưới /chat/ | 50 request mỗi giây |
Thanh toán: /payments và /einvoices | 20 request mỗi giây |
Email và phần còn lại: /emails, /domains, /templates, /contacts, /audiences, /segments, /topics, /broadcasts, /automations, /events, /webhooks, /api-keys, /logs, /usage | 10 request mỗi giây |
Mỗi module có hạn mức riêng: một đợt gửi email dồn dập không làm chậm các lời gọi chat hay thanh toán.
Chat gateway tại chat.hatang.dev, nơi widget và SDK di động kết nối, có giới hạn riêng về khách truy cập và tin nhắn. Xem Giới hạn.
Header giới hạn tần suất
Mọi response của endpoint có giới hạn tần suất đều kèm các header sau:
| Header | Ý nghĩa |
|---|---|
ratelimit-limit | Số request được phép trong một cửa sổ của module này |
ratelimit-remaining | Số request còn lại trong cửa sổ hiện tại |
ratelimit-reset | Số giây tới khi cửa sổ làm mới (luôn là 1) |
retry-after | Chỉ có khi nhận 429: số giây cần chờ trước khi thử lại |
HTTP/1.1 429 Too Many Requests
ratelimit-limit: 10
ratelimit-remaining: 0
ratelimit-reset: 1
retry-after: 1
content-type: application/json
{
"statusCode": 429,
"name": "rate_limit_exceeded",
"message": "Too many requests. You can only make 10 requests per second."
}
Hạn mức email hằng ngày
Ngoài giới hạn mỗi giây, mỗi doanh nghiệp có hạn mức email hằng ngày: số email được nhận gửi trong một ngày. Mỗi email được nhận tính một lần, dù đến từ POST /emails, gửi theo lô, SMTP relay hay chiến dịch email. Email trả lời gửi từ hộp thư Hỗ trợ không bị tính. Bộ đếm làm mới lúc 0 giờ UTC.
Vượt hạn mức, lệnh gửi nhận 429 daily_quota_exceeded:
{
"statusCode": 429,
"name": "daily_quota_exceeded",
"message": "You have reached your daily email sending quota of 10000. It resets at midnight UTC."
}
Thử lại không có tác dụng cho tới khi hạn mức làm mới. Xem hạn mức và số đã dùng hôm nay ở Email → Cài đặt email (Hạn mức hằng ngày), hoặc qua GET /usage (response đã rút gọn):
{
"object": "usage",
"emails": {
"daily": { "used": 1520, "limit": 10000, "resets_at": "2026-10-24T00:00:00.000Z" }
}
}
Thành viên có quyền Quản lý ở Email đặt được hạn mức thấp hơn hoặc cao hơn cho doanh nghiệp trong Cài đặt email, một lưới an toàn hữu ích khi code lỡ chạy vòng lặp gửi thư. Để trống ô này để dùng mặc định của nền tảng. GET /usage cần key có một scope write.
Thử lại với backoff
Chỉ thử lại 429 rate_limit_exceeded và lỗi 5xx, không thử lại lỗi 4xx do chính request gây ra. Chờ đúng retry-after giây nếu có header này, nếu không thì tăng thời gian chờ theo cấp số nhân, và cộng thêm một chút ngẫu nhiên để nhiều worker không thử lại cùng lúc. Kết hợp thử lại với Idempotency-Key để lệnh gửi lặp lại không bao giờ tạo bản trùng.
- Node.js
- Python
import { Hatang } from "@hatang/sdk";
const hatang = new Hatang(process.env.HATANG_API_KEY, { baseUrl: "https://api.hatang.dev" });
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// statusCode 0 nghĩa là không kết nối được tới API (lỗi mạng).
const retryable = (e) => e.name === "rate_limit_exceeded" || e.statusCode >= 500 || e.statusCode === 0;
async function withRetry(call, { attempts = 5 } = {}) {
for (let i = 0; ; i++) {
const result = await call();
if (!result.error || !retryable(result.error) || i === attempts - 1) return result;
const backoff = Math.min(1000 * 2 ** i, 30_000);
await sleep(backoff + Math.random() * 250);
}
}
const { data, error } = await withRetry(() =>
hatang.emails.send(
{ from: "Shop <[email protected]>", to: "[email protected]", subject: "Xin chào", html: "<p>Xin chào</p>" },
{ idempotencyKey: "welcome-user-42" },
),
);
import random, time
from hatang import Hatang, HatangError
hatang = Hatang() # đọc HATANG_API_KEY
def with_retry(call, attempts=5):
for i in range(attempts):
try:
return call()
except HatangError as err:
# thử lại được: rate_limit_exceeded (429), 5xx, hoặc không tới được API (status_code 0)
if not err.retryable or i == attempts - 1:
raise
time.sleep(min(2 ** i, 30) + random.random() / 4)
email = with_retry(lambda: hatang.emails.send(
{"from": "Shop <[email protected]>", "to": "[email protected]", "subject": "Hi", "html": "<p>Hi</p>"},
idempotency_key="welcome-user-42",
))
SDK Node.js trả về { data, error } và không tự thử lại, nên hãy bọc các lời gọi quan trọng như ví dụ trên.
Giữ dưới giới hạn
- Gửi email theo lô.
POST /emails/batchgửi tối đa 100 email trong một request, và chỉ tính là một request với giới hạn mỗi giây. - Dùng webhook thay vì hỏi liên tục. Đăng ký
email.deliveredhaychat.message.createdthay vì hỏi trạng thái trong vòng lặp (Webhook). - Xếp hàng việc lớn. Chạy import và đồng bộ qua hàng đợi với số luồng cố định thay vì bắn mọi request cùng lúc.
- Đọc header. Giảm tốc khi
ratelimit-remaininggần về0.