ZupiChat
ZupiChat
Product
Home Features Pricing
Solutions
Real Estate Healthcare Education E-commerce Agency Program
Resources
Blog Free Tools Case Studies Help Center Developer API Changelog
Compare
vs Wati vs AiSensy vs Interakt
Start Free Trial Login to Dashboard Refer & Earn 20% Commission
Developer documentation

ZupiChat API

Send WhatsApp template messages, manage contacts and receive delivery events from your own application. ZupiChat is operated by Codelith Lab Private Limited and is used by other businesses to run WhatsApp on their own WhatsApp Business Accounts.

Getting started

The API is REST over HTTPS. Requests and responses are JSON. Every response carries the same envelope, so a client can branch on one field:

{ "success": true, "message": "OK", "data": { } }

Base URL

https://zupichat.com/api/v1

Three steps to your first message

  • Create a ZupiChat account and connect your WhatsApp Business number.
  • Open Developer in the dashboard and generate an API key.
  • Get one of your approved templates approved by Meta, then call POST /messages/template.

Platform model

ZupiChat is software that other businesses run their own WhatsApp on. It is operated by Codelith Lab Private Limited (Pune, India). Every customer brings their own WhatsApp Business Account — ZupiChat does not resell numbers and does not message on its own behalf through a customer's account.

What belongs to whom

Owned by the businessProvided by ZupiChat
The WhatsApp Business Account (WABA) and its ID The dashboard, inbox, chatbot builder and campaign tooling
The phone number and its display name This REST API, the webhook delivery layer and the API keys
Message templates, submitted under their own WABA Template drafting, submission and approval tracking
The conversation history and contact list Storage, search, export and the delivery-status pipeline

Every account is its own tenant

  • API keys are issued per account and scoped to it. A key can only read and write that account's contacts, templates and messages — there is no cross-account endpoint in this API.
  • Webhooks are registered per account and fire only for that account's events.
  • Each connected number carries its own Meta credentials, so one customer's token is never used to act for another.
  • Revoking a key or disconnecting a number stops ZupiChat's access to that account immediately. The WABA and the number stay with the business.

In Meta's terms: the business is the WhatsApp Business Account owner and ZupiChat is the technology provider whose software they use to operate it. Billing for conversations is Meta's, charged to the account that owns the number.

Authentication

Send your key with every request. Three forms are accepted, so the API fits whatever your HTTP client makes easy:

Authorization: Bearer zc_live_xxxxxxxxxxxxxxxx
X-API-Key: zc_live_xxxxxxxxxxxxxxxx
?apiKey=zc_live_xxxxxxxxxxxxxxxx

Only a SHA-256 hash of the key is stored, so the key itself is shown once at creation and can never be read back. Revoke a key from the dashboard and it stops working immediately — other keys keep going.

Test mode and the sandbox number

Keys come in two kinds. A zc_live_ key sends real WhatsApp messages from your own number. A zc_test_ key answers every endpoint with realistic data and never reaches Meta — nothing is billed, and your contacts, campaigns and reports stay untouched. Build the whole integration before your number is even connected.

Try it right now

This key is public on purpose. It only ever simulates, so nothing can go wrong:

curl -X POST https://zupichat.com/api/v1/messages/template \
     -H "Authorization: Bearer zc_demo_zupichat_public_sandbox" \
     -H "Content-Type: application/json" \
     -d '{ "destination": "919876543210",
           "template_name": "sandbox_welcome",
           "body_variables": ["Aditya"] }'

Test-mode responses carry two extra fields: mode and delivery (simulated or real), plus a note telling you what just happened.

Get it on a real phone

Send this on WhatsApp from the handset you want to test with:

join zupi-demo+918329608019 Open WhatsApp

That opens WhatsApp's 24-hour service window, so for the next 24 hours every test send to that number is actually delivered to it — no template approval, no WhatsApp Business Account of your own. Fair use: 20 real messages per number.

Signed in? Developer → Sandbox gives you your own join code, so joined phones and test sends stay private to your workspace.

In test modeWhat happens
GET /meReturns the sandbox identity and your join code.
GET /templatesThree fixed templates: sandbox_welcome, order_confirmation_update, otp_login_code.
POST /messages/templateSimulated, unless the destination has joined the sandbox.
GET /messages/{id}Ages sent → delivered → read, so polling code has something to poll.
GET|POST /contactsFixture contacts. Nothing is written to your account.
WebhooksFire as usual with "mode": "test" in the payload.

Account

GET /api/v1/me

Confirms the key works and tells you which WhatsApp number it is bound to. Useful as a health check after a customer pastes their key into your product.

curl https://zupichat.com/api/v1/me \
  -H "Authorization: Bearer zc_live_xxxxxxxxxxxxxxxx"
{
  "success": true,
  "message": "OK",
  "data": {
    "account":  { "id": 13, "name": "Aditya Sonawane", "email": "owner@example.com" },
    "whatsapp": { "connected": true, "display_name": "Zupi Chat",
                  "phone_number": "918329608019", "phone_number_id": "1164348036759819" }
  }
}

Templates

GET /api/v1/templates

Lists the message templates on the connected WhatsApp Business Account with their approval status, so you can show your users only what can actually be sent.

curl https://zupichat.com/api/v1/templates \
  -H "Authorization: Bearer zc_live_xxxxxxxxxxxxxxxx"

Send a template message

POST /api/v1/messages/template

Template messages are the only way to start a conversation outside WhatsApp's 24-hour window, which is why this is the endpoint most integrations need.

FieldTypeNotes
destination requiredstringRecipient in international format, e.g. 919876543210.
template_namestringName of an approved template. Use this or template_id.
template_idintegerZupiChat's own id for the template.
body_variablesarrayValues for {{1}}, {{2}}… in order.
header_variablesarrayValues for a variable in the header, if the template has one.
namestringContact name to save when this number is new to the account.
campaign_namestringLabel the send so it can be grouped in reports.
curl -X POST https://zupichat.com/api/v1/messages/template \
  -H "Authorization: Bearer zc_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
        "destination": "919876543210",
        "template_name": "order_confirmation_update",
        "name": "Aditya",
        "body_variables": ["Aditya", "#1042"]
      }'

Message status

GET /api/v1/messages/{id}

Returns what WhatsApp last reported for that message — sent, delivered, read or failed. Poll it if you are not using webhooks.

curl https://zupichat.com/api/v1/messages/2340 \
  -H "Authorization: Bearer zc_live_xxxxxxxxxxxxxxxx"

Contacts

GET /api/v1/contacts
POST /api/v1/contacts

Read the contact book, or push a lead into it the moment it appears in your own system.

FieldTypeNotes
mobile requiredstringInternational format, e.g. 919876543210.
firstnamestringUp to 60 characters.
lastnamestringUp to 60 characters.
notestringFree text kept with the contact, up to 500 characters.
curl -X POST https://zupichat.com/api/v1/contacts \
  -H "Authorization: Bearer zc_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "mobile": "919876543210", "firstname": "Aditya", "note": "Came from the pricing page" }'

Webhooks

Register an endpoint in Developer → Webhooks and ZupiChat posts events to it as they happen, so you do not have to poll.

EventFires when
message.receivedA customer sends a message to your WhatsApp number.
message.sentYou send a message, from the panel or through this API.
message.statusWhatsApp reports a message as sent, delivered, read or failed.
contact.createdA number reaches your account for the first time.

Verifying the signature

Every delivery carries an HMAC of the raw body, signed with the secret shown when you created the webhook. Compare it before trusting the payload:

X-ZupiChat-Event:     message.status
X-ZupiChat-Delivery:  9f2c1b7a4e5d6c30
X-ZupiChat-Signature: sha256=<hmac_sha256(raw_body, your_webhook_secret)>

Answer 2xx within 3 seconds. Anything slower is logged as a failed delivery and shows up in Developer → Request Log.

{
  "event": "message.status",
  "created_at": "2026-08-22T11:08:04+05:30",
  "data": { "message_id": 2340, "whatsapp_message_id": "wamid.HBgMOTE4...",
            "conversation_id": 74, "status": "delivered" }
}

OpenAPI & Postman

The whole contract is published as a machine-readable spec, generated from the same source the endpoints run on — so it cannot drift out of date. Import it and your client, types and tests come out of it.

Use it

In Postman: Import → Link and paste either URL. Set the collection variable apiKey once and every request is authenticated. Prefer to read it in a browser? Open it in Swagger Editor.

# generate a typed client in any language
npx @openapitools/openapi-generator-cli generate \
    -i https://zupichat.com/openapi.json -g typescript-axios -o ./zupichat

Errors

Failures use standard HTTP codes and the same envelope with "success": false.

CodeMeaning
401No API key was sent, or the key is invalid or revoked.
403The account behind the key is inactive.
404The template, message or contact does not belong to this account.
429Too many calls on the public sandbox key from one IP. Your own key has no such cap.
422A field is missing or malformed — the message says which.

Limits and fair use

ZupiChat does not add its own throughput cap. What governs your volume is WhatsApp's own messaging tier for the connected number, which Meta raises as your quality rating and traffic grow.

Two rules are enforced on every send, because they are what keeps a number healthy: a contact who has opted out is never messaged, and a template can only be used once Meta has approved it.

Versioning

The version lives in the path. v1 is stable: fields get added, never removed or renamed, so an integration written today keeps working. Anything that would break a client ships under a new prefix instead, and the OpenAPI document above is generated from the running code, so it always matches what the API does.

Questions, or need an endpoint that is not here yet? Write to support@zupichat.com — the API grows with what integrators actually ask for.

Chat on WhatsApp

We may utilize cookies when you access our website, including any related media platforms or mobile applications. These technologies are employed to enhance site functionality and optimize your interactions with our services.