Docs / API reference

API reference

Send WhatsApp messages from your own software, and receive every inbound message and delivery update on your own server. No dashboard required once you have a key.

Authentication

Every request needs your API key, as a header:

Authorization: Bearer <your API key>

or

X-API-Key: <your API key>

Create and revoke keys from your eSampark dashboard (Developer Access panel, under the API tab). A key is shown once, at creation — copy it then, because it can't be shown again.

A new key can be scoped to send (sending messages, running broadcasts) or manage (templates, business profile, media, bots), or left with both — the dashboard calls that “full access.” Scope a key to just what your integration actually does; a leaked send-only key can't touch your templates or profile.

Endpoints

POST /api/messages/sendSend a text, template, media, or interactive (buttons/list) message.
GET /api/messages/status?id=…Look up what happened to a message you sent.
POST /api/campaignsCreate a broadcast campaign.
POST /api/campaigns/[id]/runStart sending a campaign.
GET/POST /api/templatesList or create WhatsApp templates.
GET/POST /api/botsList or manage bot flow definitions.
GET/PUT /api/business-profileRead or update your WhatsApp business profile.
POST /api/business-profile/pictureSet the profile picture.
POST /api/media/uploadUpload media to attach to a send.
GET/POST /api/conversational-componentsManage WhatsApp Flows components.

Sending a message

POST /api/messages/send
{
  "wabaId": "<your WABA id>",
  "to": "919876543210",
  "kind": "template",
  "templateName": "order_confirmation",
  "templateParams": ["Asha", "#1234"],
  "consentConfirmed": true
}
  • kind is "text" (default), "template", "media", or "interactive".
  • Outside WhatsApp's 24-hour customer-service window, only a template send succeeds — WhatsApp enforces this, not eSampark.
  • consentConfirmed: true is required the first time you message a recipient with no consent record. Remembered after that.
  • A template that's rejected or paused is refused with a plain reason, before anything is sent.

The response hands back WhatsApp's own message id:

{ "ok": true, "result": { "messages": [{ "id": "wamid.HBgL..." }] } }

Reply buttons and lists

Up to 3 reply buttons, or a list of up to 10 rows across one or more sections. Both only deliver inside the 24-hour window, same as a text message.

{
  "wabaId": "<your WABA id>",
  "to": "919876543210",
  "kind": "interactive",
  "consentConfirmed": true,
  "interactive": {
    "kind": "buttons",
    "bodyText": "Would you like to confirm your order?",
    "buttons": [
      { "id": "confirm", "title": "Yes, confirm" },
      { "id": "cancel", "title": "No, cancel" }
    ]
  }
}

Limits: a button title is 20 characters, its id 256; a list row title is 24 characters, its description 72, its id 200, the list's button label 20; at most 10 rows total. The reply a customer taps arrives on your webhook as an ordinary "message" event, with choice: { id, title } carrying which one.

Checking what happened to a message

GET /api/messages/status?id=<waMessageId>

<waMessageId> is the id sending a message handed back, above. A pull, not a replacement for the webhook — use this to check a specific message right now; use the webhook if you need to know the moment something changes.

{
  "ok": true,
  "waMessageId": "wamid.HBgL...",
  "to": "919876543210",
  "status": "delivered",
  "errorCode": null,
  "friendlyStatus": { "label": "Delivered" },
  "sentAt": "2026-10-12T10:00:00.000Z",
  "updatedAt": "2026-10-12T10:00:05.000Z"
}

status is WhatsApp's own word — sent, delivered, read, or failed — absent until the first status event arrives, usually seconds after the send. A 404 means eSampark has no record of that id for your account.

Webhooks — events sent to your server

Set your endpoint in the dashboard's Developer Access panel. eSampark POSTs to it for an inbound message ("message"), a delivery status update ("status"), or a copy of your own outbound send ("message_echo").

{
  "type": "message",
  "from": "919876543210",
  "contactName": "Asha",
  "messageId": "wamid.HBgL...",
  "messageType": "text",
  "text": "Yes, confirm my order",
  "timestamp": "1757620800",
  "wabaId": "<your WABA id>",
  "phoneNumberId": "<the sending number's id>"
}

Verifying the signature

Every request carries X-eSampark-Signature-256: sha256=<hex hmac>, computed over the raw request body with your signing secret (shown once, same place as your API key).

import crypto from "node:crypto";

function fromESampark(rawBody, header, secret) {
  const expected =
    "sha256=" + crypto.createHmac("sha256", secret).update(rawBody, "utf8").digest("hex");
  return header.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}

Use the exact raw bytes of the body — re-serializing a parsed object can reorder keys and break the check.

Prove it reaches you, before you build on it

Point your webhook target at https://esampark.lifesecret.co/api/dev/webhook-echo and press “Send a test event” in the dashboard first. It's a real endpoint that only logs what arrives and answers 200 — a successful test confirms delivery actually works over a real network hop, before you point the same target at your own, more complex receiver.

Not reachable with an API key

Dashboard login only, for now: reading contacts, browsing full inbox/message history, pausing or cancelling a campaign, changing your webhook target, managing API keys themselves. If your integration needs one of these, ask — this is current behavior, not a finalized design.

Rate limits

Per account, not per key: a requests-per-minute cap and a daily message cap, both set by eSampark. No per-key breakdown yet if you're using more than one key.

Known gaps, stated directly

  • Webhook delivery gets one retry on a timeout, network error, or 5xx — never on a 4xx. Beyond that, a still-down endpoint means that event isn't redelivered; there's no queue behind it.
  • No per-key usage attribution — a tenant's rate limits are shared across all of that tenant's keys.
  • No machine-readable spec yet (no OpenAPI/Swagger JSON, no Postman collection).

Questions, or something looks wrong?

Contact whoever gave you access to eSampark. Don't guess at an undocumented field — ask, and this page gets corrected.