Zalo onboarding: connect your Official Account and send ZNS templates
This guide takes a Zalo channel from nothing to a working production integration: Official Account provisioning, the template-only send, inbound replies, and delivery statuses. The field and error reference lives on the Zalo channel page — this guide is the ordered path you run the first time. For the region-wide survey of LINE, WeChat, KakaoTalk, and Zalo, see APAC channels onboarding. Zalo is a beta channel. The send and receive paths are wired end to end, but the Official Account, template approvals, and the ZNS access token are provisioned off-Orbit in the Zalo for Developers console.1. Prerequisites: Official Account and consent
- Create a Zalo Official Account (OA) in the Zalo for Developers console. The OA is the sender identity on every ZNS notification.
- Register your ZNS templates in the same console and wait for Zalo approval. Each approved template receives a template id — that id is what
template_namereferences on a send. An edited template is a new approval. - Generate the OA access token (OAuth
oauth/access_tokengrant) and paste it in Orbit under Settings → Channels → Zalo. The token is short-lived; rotate it through Zalo’s grant before it expires. Orbit stores it encrypted at rest and never echoes it back through any API response.
CHANNEL_NOT_CONFIGURED (503).
2. Template-based send — no free-form body
ZNS is template-only: a business sends a pre-approved notification template to a customer’s phone number. The send body onPOST /api/v1/messages/zalo carries to and template_name, plus an optional flat template_params map filling the template’s named variables. There is no free-form body field — a send without an approved template_name is rejected with VALIDATION_ERROR (422).
202 Accepted — the message is queued; the terminal delivered / failed state arrives later on the delivery-status webhook. Carry your own correlation key in metadata — it is echoed back on those events.
The sender is resolved automatically from the OA credentials connected to your organization; you never pass an access token on the request. The direct endpoint is capped at 80 requests/minute per organization — stage bulk template sends through the Campaigns API with channel: "zalo", where message_template and variables map to template_name and template_params.
3. Samples: curl, Node.js, Python
- curl
- Node.js
- Python
4. Inbound replies and delivery statuses
There is no Zalo webhook to register. Inbound replies and ZNS delivery callbacks land on your account’s standard webhooks — subscribe under Settings → Webhooks:- Inbound replies arrive on
message.receivedwithchannel: "zalo", folded onto the normalized inbound event envelope. Branch ondata.normalized.kind === "inbound"instead of parsing event strings. - Delivery status advances the outbound message to
delivered/failed, reconciled by the tracking id Orbit mints per send. Yourmetadatamap rides along on the event.
X-Orbit-Signature header before trusting any event — Verify webhook signatures.
5. Common errors
See also
- Zalo channel page — field reference, error codes, and credential handling.
- APAC channels onboarding — LINE, WeChat, KakaoTalk, and Zalo in one survey.
- Template-only Asia channels playbook — one approved template across every template channel.
- Campaigns API — bulk template sends.
- Message suppression — per-recipient opt-out handling.