@hatang/sdk
v0.6.2
Published
Official Node.js SDK for Ha Tang (hatang.dev): transactional email API, support inbox and live chat (Zalo, Messenger, Instagram, TikTok Shop), orders, VietQR payments and e-invoices for Vietnam.
Maintainers
Readme
@hatang/sdk
The official Node.js SDK for Ha Tang: transactional email API, support inbox and live chat (website, app, Zalo, Messenger, Instagram, TikTok Shop), customers, orders, VietQR payments and e-invoices. Typed, no dependencies, talks to https://api.hatang.dev.
npm install @hatang/sdkimport { Hatang } from "@hatang/sdk";
const hatang = new Hatang("ht_...", { baseUrl: "https://api.hatang.dev" });
const { data, error } = await hatang.emails.send({
from: "Acme <[email protected]>",
to: ["[email protected]"],
subject: "Hello",
html: "<p>Hi</p>",
});Every method resolves to { data, error } and never throws for API errors. Env fallbacks: HATANG_API_KEY / EMAIL_API_KEY for the key, HATANG_BASE_URL / EMAIL_API_URL for the base URL.
Pass a React Email react element and the SDK renders it to html (and a plain-text text if you did not supply one) before calling the API.
import { WelcomeEmail } from "./emails/welcome";
await hatang.emails.send({ from, to, subject: "Welcome", react: <WelcomeEmail name="Ada" /> });Received mail (domains with receiving on): emails.receiving.list(), .get(id), .attachments.list(id) / .get(id, attachmentId); turn it on with domains.update({ id, capabilities: { receiving: "enabled" } }).
Namespaces: emails, batch, domains, apiKeys, webhooks, audiences, contacts, broadcasts, payments, einvoices, chat.
Chat (support inbox, customers, orders)
Everything the inbox does, for your own systems: read conversations from the website widget, Zalo, Messenger, Instagram and TikTok Shop, reply as an agent, keep customers and orders in step with your ERP. Keys need the chat:read scope for reads and chat:write for writes (replies, orders, tickets, sites, products, settings). chat:reply and chat:manage are employee role permissions inside the dashboard, not API key scopes.
// Unanswered conversations, oldest first
const { data: open } = await hatang.chat.conversations.list({ status: "open", unanswered: true });
// Reply (an Idempotency-Key makes retries safe) and leave a private note
await hatang.chat.conversations.send(open.data[0].id, { content: "Dạ shop còn hàng ạ" }, { idempotencyKey: "reply-42" });
await hatang.chat.conversations.send(open.data[0].id, { content: "Khách VIP", visibility: "private" });
// Assign, tag, resolve
await hatang.chat.conversations.update(open.data[0].id, { assignee_id: "usr_...", tags: ["vip"], status: "resolved" });
// The timeline (messages and events) after a sequence number, for syncing
const { data: page } = await hatang.chat.conversations.messages("cnv_...", { after_seq: 120, limit: 200 });
// An order from the conversation, then a VietQR payment link posted into it
const { data: order } = await hatang.chat.orders.create({ conversation_id: "cnv_...", items: [{ name: "Trà sen 100g", price: 120_000, quantity: 2 }], send_card: true });
const { data: link } = await hatang.chat.orders.paymentLink(order.id, { expires_in: 3600 });
// Orders mirrored from TikTok Shop carry the channel's own id and status (order.source, external_id, external_status)
// Customers across channels: search, update, merge duplicates, export
const { data: customers } = await hatang.chat.customers.list({ stage: "qualified", channel: "instagram" });
await hatang.chat.customers.merge("cus_a", ["cus_b"]);
const { data: csv } = await hatang.chat.customers.exportCsv({ label: "wholesale" });
// Products (also importable from CSV, a Google Sheet link or a website's schema.org data)
await hatang.chat.products.import({ url: "https://docs.google.com/spreadsheets/d/.../pub?output=csv" });
// Tickets, live visitors, canned responses, Zalo ZNS, reports
await hatang.chat.tickets.create({ title: "Đổi size", priority: "high", conversation_id: "cnv_..." });
const { data: live } = await hatang.chat.live.list();
await hatang.chat.live.greet(live.data[0].id, "Chào chị, em giúp gì được ạ?");
const { data: report } = await hatang.chat.reports.get({ from: "2026-09-01", to: "2026-09-30" });Webhook events for chat (chat.conversation.created, chat.message.created, chat.order.paid, chat.ticket.created, …) arrive through the same webhooks endpoints and constructWebhookEvent as everything else.
Payments
const hatang = new Hatang(process.env.HATANG_API_KEY, { environment: "development" }); // drop in production
// Create the payment for an order (safe to retry: the order id is the idempotency key)
const { data: payment } = await hatang.payments.createOrder({ order_id: "SO-1001", amount: 150_000, ipn_url: "https://shop.example.vn/api/hatang/ipn" });
// → payment.checkout_url, payment.qr.image_url, payment.code
// `code` makes the transfer description your own order number instead of a generated HT… one
await hatang.payments.createOrder({ order_id: "SO-1002", amount: 275_000, code: "SO1002" });
// Your IPN endpoint: verify the HMAC signature on the raw body, get the call
import { constructIpnEvent } from "@hatang/sdk";
const ipn = await constructIpnEvent(rawBody, request.headers, process.env.HATANG_SECRET_KEY); // throws HatangSignatureError
// Before fulfilling: ask Ha Tang whether it is really paid for this order
const { data: check } = await hatang.payments.verify(payment.id, { order_id: "SO-1001", amount: 150_000 });
if (check.verified) fulfil();
// Webhooks (Svix signature, 5-minute window)
import { constructWebhookEvent } from "@hatang/sdk";
const event = await constructWebhookEvent(rawBody, request.headers, process.env.HATANG_WEBHOOK_SECRET);constructIpnEvent, verifyIpn, constructWebhookEvent and verifyWebhook use Web Crypto only and run in Node 20+, Bun, Deno and edge runtimes. The full guide (flows, invoices, testing) is the Payments guide.
About Ha Tang
Ha Tang (Hạ Tầng) is a customer support platform for businesses in Vietnam: one inbox for your website, mobile app, Zalo, Messenger, Instagram, TikTok Shop, WhatsApp and email, with an AI assistant, plus a transactional email API, VietQR payments and e-invoices.
- Product: hatang.dev/email
- Guide: Ha Tang Node.js SDK (Tiếng Việt)
- API reference: @hatang/sdk
- REST API: hatang.dev/docs/reference/api
- AI coding agents: MCP server and rules
- Changelog: hatang.dev/docs/changelog
- Support: hatang.dev/contact
