Developers

ZeniaOne API

Send and receive WhatsApp messages from your own systems over a simple REST API. Authenticate with an API key, then send text, templates and media, manage contacts, and get delivery updates through webhooks. All examples below use the placeholder number 919999999999 and YOUR_API_KEY โ€” swap in your own to go live.

Base URL

Every endpoint lives under a single versioned base URL. Requests and responses are JSON.

base url
https://zeniaone.com/api/v1

The complete, always-current, interactive reference (every endpoint and field) is published as OpenAPI at zeniaone.com/api/docs.

Authentication

Create an API key in your dashboard under Settings โ†’ API & Webhooks. Send it on every request in the X-Api-Key header. The key identifies your workspace, so you never send a workspace id.

every request
X-Api-Key: YOUR_API_KEY
Content-Type: application/json

Each key is limited to the scopes you grant it โ€” request only what you need:

ScopeGrants
messages:sendSend messages & templates
messages:readRead message status & history
contacts:readRead contacts
contacts:writeCreate / update contacts
templates:readRead templates
templates:writeCreate / submit / manage templates
campaigns:readRead campaigns
campaigns:writeLaunch / schedule / manage campaigns
media:writeUpload media
webhooks:manageManage outbound webhooks

Send a message

POST /messages sends to a recipient. Give the recipient in to (their number in international format, digits only, no +), or send into an existing chat with conversationId. Scope: messages:send.

Text

curl
curl -X POST https://zeniaone.com/api/v1/messages \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",
    "to": "919999999999",
    "body": "Hello from ZeniaOne ๐Ÿ‘‹"
  }'

A successful call returns the created message:

200 response (example)
{
  "id": "cmt4rtf8300blpi010axy500m",
  "waMessageId": "wamid.HBgMOTE5OTk5OTk5OTk5...",
  "type": "TEXT",
  "status": "SENT"
}

Template

Outside the 24-hour service window you must send an approved template. In templateId pass the template name exactly as it appears in WhatsApp Manager (its internal id also works), and fill its {{1}} variables in order. The template used is the approved copy on the number you send from; add an optional language if the same name exists in more than one language.

curl
curl -X POST https://zeniaone.com/api/v1/messages \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "template",
    "to": "919999999999",
    "templateId": "welcome_message_website",
    "variables": ["Ravi", "ORD-1234"]
  }'

Media (image, video, document, audio)

curl
curl -X POST https://zeniaone.com/api/v1/messages \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "image",
    "to": "919999999999",
    "link": "https://example.com/receipt.jpg",
    "caption": "Your receipt"
  }'

Optional fields: phoneNumberId (which of your WhatsApp numbers to send from; defaults to your primary), contextMessageId (reply to a message), and filename for documents. Interactive buttons, lists, location and reactions are also supported โ€” see the full reference.

Check delivery status

GET /messages/{waMessageId}returns a message's current status. Scope: messages:read.

curl
curl https://zeniaone.com/api/v1/messages/wamid.HBgMOTE5OTk5... \
  -H "X-Api-Key: YOUR_API_KEY"

Status moves through SENT โ†’ DELIVERED โ†’ READ, or FAILED with a reason. Prefer webhooks (below) for real-time updates instead of polling.

Contacts

Create or update a contact. Upserts on the WhatsApp number, so calling it twice for the same number updates the record. Scope: contacts:write (read: contacts:read).

curl
curl -X POST https://zeniaone.com/api/v1/contacts \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "waId": "919999999999",
    "name": "Ravi Kumar",
    "email": "ravi@example.com"
  }'

Templates

List your message templates and their approval status. Scope: templates:read.

curl
curl "https://zeniaone.com/api/v1/templates?status=APPROVED" \
  -H "X-Api-Key: YOUR_API_KEY"

Webhooks

Register a webhook URL under Settings โ†’ API & Webhooks to receive events as JSON POSTs: inbound messages from customers and delivery-status updates (sent, delivered, read, failed). This is the recommended way to build real-time integrations.

inbound message event (example)
{
  "event": "message.received",
  "workspaceId": "ws_...",
  "conversation": { "id": "...", "contact": { "waId": "919999999999", "name": "Ravi Kumar" } },
  "message": { "type": "text", "body": "Hi, is this available?", "waMessageId": "wamid...." }
}

Each delivery is signed so you can verify it came from ZeniaOne. Configure the URL and see the exact payloads in your dashboard.

Rate limits

Each API key has a per-minute rate limit (300 requests/minute by default; configurable per key). Every response includes headers so you can back off gracefully:

response headers
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-RateLimit-Reset: 42

Errors

Errors return a JSON body with a message and the right HTTP status:

HTTPMeaning
400Invalid request body or missing a required field
401Missing or invalid API key
403The key lacks the required scope
404Resource not found
429Rate limit exceeded โ€” retry after X-RateLimit-Reset seconds

A send can succeed (the API returns the message) and still fail at delivery for a WhatsApp policy reason, reported later on the message status. Common ones: 131049 (a per-recipient marketing-frequency cap โ€” try a different recipient or a utility template), 131047 (re-engagement needed โ€” send an approved template), and 131026(the number can't receive WhatsApp messages).

Full reference

Browse and try every endpoint interactively in the OpenAPI reference:

Open the interactive API reference โ†’