Developer Documentation

Vesper API Documentation

Everything you need to integrate WhatsApp: authentication, sessions, sending messages, and real-time webhooks — with copy-paste examples in cURL, Node.js, PHP, and Python.

Quick Start

Send your first WhatsApp message in 3 steps:

1

Create a session & scan the QR code

cURL
curl -X POST https://api.vespergateway.com/api/v1/sessions \
  -H "x-api-key: vsp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-whatsapp"}'
2

Get the QR code & scan it with your phone (WhatsApp > Settings > Linked Devices)

cURL
curl https://api.vespergateway.com/api/v1/sessions/SESSION_ID/qr \
  -H "x-api-key: vsp_your_key"
3

Send a message

curl -X POST https://api.vespergateway.com/api/v1/messages/send/text \
  -H "x-api-key: vsp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "session": "SESSION_ID",
    "to": "905551234567",
    "text": "Hello from Vesper! 🚀"
  }'

Base URL: https://api.vespergateway.com/api/v1 — every endpoint is prefixed with /api/v1 and uses JSON for requests and responses.

Tools & resources

Authentication

Every API request requires an API key. Pass it in the x-api-key header:

curl -H "x-api-key: vsp_abc123def456" \
  https://api.vespergateway.com/api/v1/sessions
x-api-keyheaderREQUIREDYour API key (starts with vsp_)

API keys are generated in your app settings and shown only once — copy and store yours securely. You can revoke and regenerate keys at any time.

Sessions

A session is a WhatsApp connection linked to a phone number. Create one, scan the QR code, and it stays connected with automatic reconnect.

Endpoints

POST
/sessions

Create a new WhatsApp session

GET
/sessions

List all your sessions

GET
/sessions/:id

Get session details (status, phone, name)

GET
/sessions/:id/qr

Get the QR code as a base64 image for pairing

GET
/sessions/:id/status

Check connection status (connected / connecting / disconnected)

POST
/sessions/:id/restart

Restart the session (re-connect WhatsApp)

DELETE
/sessions/:id

Permanently delete the session and all its data

Create a session

curl -X POST https://api.vespergateway.com/api/v1/sessions \
  -H "x-api-key: vsp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "store-whatsapp"}'

Request body:

namestringREQUIREDUnique session name (1-64 characters)

Session lifecycle

connectingscan QRconnected

Poll GET /sessions/:id/qr every 3-5 seconds. When the status becomes connected, the QR was scanned successfully. Sessions auto-reconnect if the connection drops.

Messages

Send text, images, videos, documents, audio, and location messages. All send endpoints follow the same pattern.

Send endpoints

POST
/messages/send/text

Send a text message

POST
/messages/send/image

Send an image (URL or base64)

POST
/messages/send/video

Send a video (URL)

POST
/messages/send/document

Send a file (PDF, DOCX, etc.)

POST
/messages/send/audio

Send audio or a voice note

POST
/messages/send/location

Send a location pin

History endpoints

GET
/messages/:sessionId

Get message history (paginated, optional ?jid= filter)

GET
/messages/:sessionId/:msgId

Get a single message by ID

DELETE
/messages/:sessionId/:msgId

Delete a message from the database

Send a text message

curl -X POST https://api.vespergateway.com/api/v1/messages/send/text \
  -H "x-api-key: vsp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "session": "SESSION_ID",
    "to": "905551234567",
    "text": "Hello from Vesper! 🚀"
  }'
sessionstringREQUIREDSession ID
tostringREQUIREDRecipient phone (international format, no + or spaces)
textstringREQUIREDMessage text (supports emojis)

Send an image

cURL
curl -X POST https://api.vespergateway.com/api/v1/messages/send/image \
  -H "x-api-key: vsp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "session": "SESSION_ID",
    "to": "905551234567",
    "url": "https://example.com/photo.jpg",
    "caption": "Check this out!"
  }'
urlstringREQUIREDPublic image URL (JPEG, PNG, WebP)
captionstringOptional caption text

Send a document

cURL
curl -X POST https://api.vespergateway.com/api/v1/messages/send/document \
  -H "x-api-key: vsp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "session": "SESSION_ID",
    "to": "905551234567",
    "url": "https://example.com/report.pdf",
    "filename": "Q1-Report.pdf"
  }'
urlstringREQUIREDPublic file URL
filenamestringREQUIREDDisplay filename (e.g. report.pdf)
captionstringOptional caption text

Send a location

cURL
curl -X POST https://api.vespergateway.com/api/v1/messages/send/location \
  -H "x-api-key: vsp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "session": "SESSION_ID",
    "to": "905551234567",
    "latitude": 41.0082,
    "longitude": 28.9784,
    "name": "Istanbul"
  }'

Message response

JSON
{
  "success": true,
  "data": {
    "key": { "remoteJid": "905551234567@s.whatsapp.net", "fromMe": true, "id": "3EB0A8C2F5B7..." },
    "status": "PENDING"
  }
}

Phone format: international format without + or spaces. Examples: 905551234567 (Turkey), 491621234567 (Germany), 447911123456 (UK).

Message status tracking

pendingsentdeliveredread

Status updates are tracked automatically. Subscribe to the message.sent, message.delivered, and message.read webhook events to follow each message.

Webhooks

Webhooks notify your server in real time when events happen — messages received, delivered, read, sessions connecting or disconnecting, and more. Register a URL, pick the events you want, and Vesper sends a POST request to it.

Management endpoints

POST
/webhooks

Create a new webhook

GET
/webhooks

List all webhooks

GET
/webhooks/:id

Get webhook details

PUT
/webhooks/:id

Update webhook URL, events, or secret

DELETE
/webhooks/:id

Delete a webhook

POST
/webhooks/:id/test

Send a test payload to verify your endpoint

GET
/webhooks/:id/logs

View recent delivery logs (success / fail)

Create a webhook

cURL
curl -X POST https://api.vespergateway.com/api/v1/webhooks \
  -H "x-api-key: vsp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/vesper/webhook",
    "events": ["message.received", "message.delivered", "message.read"],
    "secret": "your_webhook_secret_min16chars"
  }'
urlstringREQUIREDYour HTTPS endpoint that will receive POST requests
eventsstring[]REQUIREDEvents to subscribe to. Use ["*"] for all events
secretstringMin 16 characters. Used to sign payloads with HMAC-SHA256

Payload format

Every webhook delivery is a POST request with this structure:

JSON
{
  "event": "message.received",
  "timestamp": "2026-06-24T10:30:00.000Z",
  "session": "YoNofiM9vtHy",
  "data": {
    "id": "3EB0A8C2F5B7E6A1",
    "from": "905551234567@s.whatsapp.net",
    "type": "text",
    "content": { "text": "Hey, is my order ready?" },
    "pushName": "Ahmet"
  }
}

Headers sent with each delivery

Content-Typeheaderapplication/json
User-AgentheaderVesper-Webhook/1.0
X-Vesper-Eventheadermessage.received
X-Vesper-Deliveryheadernanoid
X-Vesper-Signatureheadersha256=…

Verify the signature

const crypto = require("crypto");

function verify(rawBody, signature, secret) {
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  return signature === expected;
}

Important: respond with a 2xx status within 10 seconds or the delivery will be retried. Failed deliveries retry up to 5 times with exponential backoff (1s, 2s, 4s, 8s, 16s).

Webhook Events

Detailed payload examples for each event type, so you know exactly what your server will receive.

message.receivedA new message was received from someone
JSON
{
  "event": "message.received",
  "timestamp": "2026-06-24T10:30:00.000Z",
  "session": "YoNofiM9vtHy",
  "data": {
    "id": "3EB0A8C2F5B7E6A1",
    "from": "905551234567@s.whatsapp.net",
    "type": "text",
    "timestamp": 1750761000,
    "content": { "text": "Hey, is my order ready?", "caption": "", "mimetype": "", "filename": "", "base64": "" },
    "pushName": "Ahmet"
  }
}

type can be text, image, video, audio, document, location, sticker, contact, or reaction. For media messages, base64 contains the file data and mimetype tells you the format.

message.from_phoneYou sent a message from your phone (not via the API)
JSON
{
  "event": "message.from_phone",
  "timestamp": "2026-06-24T10:31:00.000Z",
  "session": "YoNofiM9vtHy",
  "data": {
    "id": "3EB0B9D3E6C8F7B2",
    "to": "905551234567@s.whatsapp.net",
    "type": "text",
    "content": { "text": "Yes, it will be ready in 10 minutes!" },
    "pushName": "My Business"
  }
}

Use this event to sync messages sent from your phone into your CRM, helpdesk, or any external system. The message is also stored in Vesper's database.

message.sentmessage.deliveredmessage.read

Track your message's journey — the same payload structure is used for all three events:

JSON
{
  "event": "message.delivered",
  "timestamp": "2026-06-24T10:30:05.000Z",
  "session": "YoNofiM9vtHy",
  "data": { "id": "3EB0A8C2F5B7E6A1", "session": "YoNofiM9vtHy", "remoteJid": "905551234567@s.whatsapp.net" }
}
sent = reached WhatsApp serversdelivered = on the recipient's phoneread = recipient opened the chat
message.updatedA message was edited
JSON
{
  "event": "message.updated",
  "timestamp": "2026-06-24T10:35:00.000Z",
  "session": "YoNofiM9vtHy",
  "data": { "id": "3EB0A8C2F5B7E6A1", "remoteJid": "905551234567@s.whatsapp.net", "message": { "conversation": "Edited message text" } }
}
session.connectedsession.disconnected
JSON
// session.connected
{
  "event": "session.connected",
  "session": "YoNofiM9vtHy",
  "data": { "session": "YoNofiM9vtHy", "phone": "905559876543", "pushName": "My Business" }
}

// session.disconnected
{
  "event": "session.disconnected",
  "session": "YoNofiM9vtHy",
  "data": { "session": "YoNofiM9vtHy", "reason": "connection_lost" }
}

reason can be connection_lost (temporary, auto-reconnects) or logged_out (the user unlinked the device — the session needs re-pairing).

All available events

message.receivedNew incoming message
message.from_phoneMessage sent from your phone
message.sentMessage reached WhatsApp servers
message.deliveredMessage delivered to recipient
message.readRecipient read the message
message.updatedMessage was edited
session.connectedWhatsApp session connected
session.disconnectedSession disconnected
session.qrNew QR code generated for pairing
group.joinParticipant added to group
group.leaveParticipant removed from group
group.updateGroup settings changed

Groups

Create and manage WhatsApp groups programmatically.

GET
/groups/:sessionId

List all groups for a session

POST
/groups/create

Create a new group

PUT
/groups/:groupId

Update group subject or description

POST
/groups/:groupId/participants/add

Add participants to a group

POST
/groups/:groupId/participants/remove

Remove participants from a group

Broadcast

Send bulk messages to recipient lists. Messages are queued and sent with smart delays to help avoid bans.

POST
/broadcast/lists

Create a recipient list

GET
/broadcast/lists

Get all recipient lists

POST
/broadcast/campaigns

Create and send a broadcast campaign

GET
/broadcast/campaigns

List all campaigns

GET
/broadcast/campaigns/:id

Get campaign details and delivery status

POST
/broadcast/campaigns/:id/cancel

Cancel an in-progress broadcast

Broadcast messages support personalization with name and surname placeholders in your text. Plan limits apply: Starter 100/mo, Pro 1,000/mo, Enterprise 5,000/mo.

Chatbot

Build automated conversation flows that respond to incoming WhatsApp messages. Create flows with steps (send text, buttons, conditions, webhooks), assign them to a session, and publish.

Flow lifecycle

DraftAssign sessionPublishLive

A flow needs an assigned WhatsApp session and at least one step before it can be published. Each session can have only one active published flow at a time.

Flow endpoints

GET
/chatbot/flows?appId=

List all chatbot flows for an app

POST
/chatbot/flows

Create a new flow

GET
/chatbot/flows/:flowId

Get flow details with steps

PUT
/chatbot/flows/:flowId

Update a flow (name, trigger, session, enabled)

DELETE
/chatbot/flows/:flowId

Delete a flow (cascades steps & sessions)

POST
/chatbot/flows/:flowId/publish

Publish a draft flow

POST
/chatbot/flows/:flowId/unpublish

Unpublish back to draft

POST
/chatbot/flows/:flowId/duplicate

Duplicate a flow with all its steps

Step endpoints

POST
/chatbot/flows/:flowId/steps

Add a step to a flow

PUT
/chatbot/flows/:flowId/steps/:stepId

Update a step

DELETE
/chatbot/flows/:flowId/steps/:stepId

Delete a step

PUT
/chatbot/flows/:flowId/steps/batch

Batch update positions & connections

Test & statistics

POST
/chatbot/flows/:flowId/simulate

Simulate flow execution with test messages

GET
/chatbot/flows/:flowId/sessions

Get flow conversation history

GET
/chatbot/stats?appId=

Get chatbot statistics for an app

Create a flow

cURL
curl -X POST https://api.vespergateway.com/api/v1/chatbot/flows \
  -H "x-api-key: vsp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "appId": "APP_ID",
    "name": "Welcome Bot",
    "triggerType": "keyword",
    "triggerValue": { "keywords": ["hello", "hi", "merhaba"], "matchType": "contains" },
    "sessionId": "SESSION_ID"
  }'
appIdstringREQUIREDApp ID
namestringREQUIREDFlow name (1-100 characters)
triggerTypestringREQUIREDkeyword | first_contact | schedule
triggerValueobjectTrigger config (keywords, matchType, schedule times)
sessionIdstringWhatsApp session ID (required to publish)

Node types reference

TypeDescriptionConfig fields
send_textSend a text messagemessage
send_imageSend an imageurl, caption
send_buttonsSend options (WhatsApp List)message, buttons[{id, label}]
wait_replyWait for a user replytimeout, timeoutAction
conditionBranch by conditionrules[{variable, operator, value}], logic
delayWait N secondsseconds
webhookCall an external APIurl, method, headers, body
set_variableAssign a variablename, source, value

Use the simulate endpoint to test your flow without sending real WhatsApp messages. Variables such as last_reply and your custom variables are resolved during execution.

Errors & Rate Limits

Error format

JSON
{
  "success": false,
  "error": {
    "code": "LIMIT_EXCEEDED",
    "message": "Monthly message limit (5000) exceeded"
  }
}

Common error codes

401UnauthorizedMissing or invalid API key
403ForbiddenPlan limit exceeded or feature not available
404Not FoundSession or resource doesn't exist
409ConflictResource already exists (duplicate session name)
429Too Many RequestsRate limit exceeded (100 requests/minute)

Plan limits

PlanAppsSessionsMessages/moBroadcast/mo
Starter €29125,000100
Pro €6931025,0001,000
Enterprise €1491050100,0005,000

Check the X-RateLimit-Remaining and X-RateLimit-Reset response headers. When you hit a limit, back off and retry after the reset time.