Hubz API v1 (beta) · Hubz v0.7.0 · 2026-11-06
Fetch missed events with GET /v1/events
Software on a private network, behind NAT (for example an Odoo installed in an office), cannot receive webhooks. It polls events with GET /v1/events instead. This is also how you recover events missed while a webhook was failing.
How to poll
- Call with
after=0the first time. - Handle the returned events in order, then store
next. - Next time, call with
after=<next>. If the page was full, call again at once; otherwise wait for the next run.
curl "https://api.hubz.vn/v1/events?after=0&limit=100" \
-H "Authorization: Bearer hbz_live_xxx"
{
"events": [
{"id": "1042", "type": "message.created", "version": 1, "createdAt": "2026-11-06T09:15:02Z", "data": {"…": "…"}},
{"id": "1043", "type": "conversation.updated", "version": 1, "createdAt": "2026-11-06T09:15:40Z", "data": {"…": "…"}}
],
"next": "1043"
}
Parameters
| Parameter | Meaning |
|---|---|
after | The next value of the previous call; 0 the first time. |
limit | Default 100, at most 500. |
types | Event types to keep, comma-separated, for example message.created,conversation.updated. |
The key needs the events scope. Events are kept for 7 days. Event ids increase: handle each id once.
Python example
import time
import requests
API = "https://api.hubz.vn"
HEADERS = {"Authorization": "Bearer hbz_live_xxx"}
def poll(after: str = "0"):
"""Fetch every new event once; store `after` between runs (events are kept 7 days)."""
while True:
res = requests.get(f"{API}/v1/events", headers=HEADERS, params={"after": after, "limit": 500}, timeout=30)
if res.status_code == 429:
time.sleep(int(res.headers.get("Retry-After", "60")))
continue
res.raise_for_status()
page = res.json()
for event in page["events"]:
handle(event) # your code: idempotent, keyed by event["id"]
after = page["next"]
if len(page["events"]) < 500:
return after
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.