Skip to Content
Beta: Hubz API v1 is being rolled out to production. Endpoints and limits may change; every change is listed in the Changelog.

Hubz API v1 (beta) · Hubz v0.7.0 · 2026-11-06

Embed the Hubz chat in your software

Embed the Hubz chat in your software so staff answer customers right from the customer record: the chat of one conversation, or the staff member's whole Hubz app.

1. Allow the page that holds the frame

The page that holds the iframe must be on the embedding list, added with PUT /v1/embed-origins (as https://your-domain) or under Integrations in Hubz:

curl -X PUT https://api.hubz.vn/v1/embed-origins \
  -H "Authorization: Bearer hbz_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"origins": ["https://crm.example.com"]}'

2. Get an embed address

From your server, call POST /v1/embed-token as the staff member who is looking (X-Hubz-User). Send {"conversationId": "…"} to embed one conversation, or {"app": true} to embed the whole app (except password, two-factor authentication, company switching and integration keys):

curl -X POST https://api.hubz.vn/v1/embed-token \
  -H "Authorization: Bearer hbz_live_xxx" \
  -H "X-Hubz-User: lan@example.com" \
  -H "Content-Type: application/json" \
  -d '{"conversationId": "…"}'
{"url": "…", "token": "…", "expiresAt": "2026-11-06T10:15:02Z"}

Put url in the iframe. The address works for 60 minutes. With a key that lacks the send scope, the frame is read only.

3. Renew without reloading

When the token is about to expire, the frame posts {type: "hubz:embed-expired"} to the page. The page gets a new token from your server and posts {type: "hubz:embed-token", token} to the frame, to Hubz's origin:

// The page that holds the iframe. Your backend calls POST /v1/embed-token with the key and
// returns { url, token }: never put the key in the browser.
const { url } = await fetch("/my-backend/hubz/embed-token").then((res) => res.json());
const hubzOrigin = new URL(url).origin;
const frame = document.querySelector("#hubz-frame");
frame.src = url;

window.addEventListener("message", async (event) => {
  if (event.origin !== hubzOrigin || event.data?.type !== "hubz:embed-expired") return;
  const { token } = await fetch("/my-backend/hubz/embed-token").then((res) => res.json());
  frame.contentWindow.postMessage({ type: "hubz:embed-token", token }, hubzOrigin);
});

Hubz is not affiliated with Zalo or VNG; Hubz does not use Zalo’s official API. Hubz is not affiliated with Odoo S.A.; Odoo is a trademark of Odoo S.A.