Skip to content

Conventions

Envelope

Success:

json
{ "success": true, "data": { }, "pagination": { "limit": 50, "has_more": true, "next_before": 1760000000000 }, "request_id": "..." }

Error:

json
{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Invalid body parameters", "details": [{ "path": "body.text", "message": "At most 10000 characters" }] }, "request_id": "..." }

Every response has an X-Request-Id header: include it when you report a problem.

Error codes

HTTP code Meaning
400 VALIDATION_ERROR, INVALID_JSON Invalid parameters
401 UNAUTHORIZED Key missing/invalid/revoked/expired
403 FORBIDDEN_SCOPE, FORBIDDEN_ACCOUNT, FORBIDDEN_IP, FORBIDDEN_ERP Insufficient permissions
404 NOT_FOUND No such endpoint or data
409 ACCOUNT_OFFLINE, CONFLICT Account not connected / conflict
413 PAYLOAD_TOO_LARGE Body/file too large
422 CHANNEL_UNSUPPORTED The channel does not support this operation
429 RATE_LIMITED, AUTH_BLOCKED Exceeded the limit you set / IP temporarily blocked
502 UPSTREAM_ERROR Zalo/Facebook/Telegram returned an error
503 API_DISABLED, WORKSPACE_UNAVAILABLE API turned off / the machine has an employee workspace open
504 TIMEOUT Processing took too long

Pagination

  • Regular lists: ?limit=50&offset=0, read pagination.next_offset.
  • Messages: newest → oldest, ?limit=50&before=<epoch ms>; for the next page use pagination.next_before. Messages sharing the same timestamp may repeat at the page boundary → deduplicate by msg_id.

Data

  • Times: epoch milliseconds.
  • Field names: snake_case, following the DB columns. JSON columns (attachments, reactions, quote) are already parsed.
  • Cookies, sessions, passwords and local file paths are never returned.
  • Account ID = accounts.zalo_id (Facebook: the Facebook ID; Telegram: the Telegram account ID).

Idempotency

For POST requests, send the header Idempotency-Key: <unique string>. Repeating a call with the same key within 24 hours returns the original result unchanged (header Idempotent-Replayed: true) instead of sending the message a second time. Temporary errors (409, 429, 5xx) are not stored, so you can retry.

Limits

  • JSON body up to 10 MB, file uploads up to 100 MB (change these in Settings, Cài đặt).
  • By default there is no rate limit. You can set a limit per key or a global default.
  • Calls are queued with at most N jobs running concurrently (default 4) so the app stays responsive; requests are never rejected because of the queue.
  • Outgoing messages go through the same per-account send queue as the app, so Zalo accounts don't get locked for sending in bursts.

Didn't find your answer?

Message us on Telegram