Overview

Uno SAP connects WhatsApp numbers to your application. The API supports two authentication models: master keys that manage your entire account and all sessions, and session-scoped keys that are tied to a single WhatsApp session for simplified access.

Base URL

https://api.beta.unosap.com/v1

Auth

Bearer sk_live_...

Content-Type

application/json

Version

v1

Get your API key from the Sessions page. Each session gets its own key. Store it securely — it's shown only once.

API Keys & Authentication

Uno SAP uses two types of API keys. Both are passed as a Bearer token in the Authorization header.

Master Key
Full account access

Master keys have access to all sessions and account-level operations. Use them from your server to create sessions, send messages on behalf of any session, and manage webhooks across your account. Found in Settings.

curl https://api.beta.unosap.com/v1/sessions \
  -H "Authorization: Bearer sk_live_master_..."
Session-Scoped Key
Single session access

Session-scoped keys are tied to one WhatsApp session. They unlock a simplified API where you never need to specify a session ID in the URL — the key itself determines the session. Available endpoints with a session-scoped key:

/send/webhooks/session/health/messages

Generate a session-scoped key from the Sessions page, or via POST /v1/sessions/:id/keys.

Authorization header format

Authorization: Bearer sk_live_...

Both key types use the same header format. The API detects the key type automatically.

Session Management

These endpoints require a master key. They manage the full lifecycle of your WhatsApp sessions.

POST/v1/sessions

Create a new WhatsApp session. Returns a session ID and a session-scoped API key.

curl -X POST https://api.beta.unosap.com/v1/sessions \
  -H "Authorization: Bearer sk_live_master_..." \
  -H "Content-Type: application/json" \
  -d '{"displayName": "Support Line"}'
{
  "id": "f496492d-...",
  "displayName": "Support Line",
  "status": "PENDING",
  "apiKey": "sk_live_ses_..."
}
GET/v1/sessions

List all WhatsApp sessions for your account.

curl https://api.beta.unosap.com/v1/sessions \
  -H "Authorization: Bearer sk_live_master_..."
[
  {
    "id": "f496492d-...",
    "displayName": "Support Line",
    "phone": "2348012345678",
    "status": "CONNECTED",
    "healthScore": 100
  }
]
GET/v1/sessions/:id

Get details for a single session.

curl https://api.beta.unosap.com/v1/sessions/f496492d-... \
  -H "Authorization: Bearer sk_live_master_..."
POST/v1/sessions/:id/reconnect

Trigger a reconnect for a disconnected session. Returns HTTP 204 on success.

curl -X POST https://api.beta.unosap.com/v1/sessions/f496492d-.../reconnect \
  -H "Authorization: Bearer sk_live_master_..."
DELETE/v1/sessions/:id

Soft-delete a session. The session is disconnected and removed from your account. Returns HTTP 204.

curl -X DELETE https://api.beta.unosap.com/v1/sessions/f496492d-... \
  -H "Authorization: Bearer sk_live_master_..."
GET/v1/sessions/:id/health

Get the health score and connectivity details for a session.

curl https://api.beta.unosap.com/v1/sessions/f496492d-.../health \
  -H "Authorization: Bearer sk_live_master_..."
{
  "score": 100,
  "status": "CONNECTED",
  "lastSeen": "2026-05-28T10:30:00Z"
}
POST/v1/sessions/:id/send

Send a WhatsApp message via a specific session using your master key.

curl -X POST https://api.beta.unosap.com/v1/sessions/f496492d-.../send \
  -H "Authorization: Bearer sk_live_master_..." \
  -H "Content-Type: application/json" \
  -d '{"to": "2348012345678", "type": "text", "text": "Hello!"}'
POST/v1/sessions/:id/pair

Request a pairing code instead of scanning a QR code. Pass the phone number in international format.

curl -X POST https://api.beta.unosap.com/v1/sessions/f496492d-.../pair \
  -H "Authorization: Bearer sk_live_master_..." \
  -H "Content-Type: application/json" \
  -d '{"phone": "2348012345678"}'
{ "code": "ABCD-1234" }

Sending Messages

Messages can be sent using either key type. Use the session-scoped POST /v1/send endpoint for single-session apps, or the master-key POST /v1/sessions/:id/send when managing multiple sessions from one key.

POST/v1/send

Send a message using a session-scoped key. The session is determined by your API key automatically.

Text

curl -X POST https://api.beta.unosap.com/v1/send \
  -H "Authorization: Bearer sk_live_ses_..." \
  -H "Content-Type: application/json" \
  -d '{"to": "2348012345678", "type": "text", "text": "Hello!"}'

Image with caption

curl -X POST https://api.beta.unosap.com/v1/send \
  -H "Authorization: Bearer sk_live_ses_..." \
  -d '{"to": "2348012345678", "type": "image", "mediaUrl": "https://example.com/photo.jpg", "caption": "Check this"}'

Document

curl -X POST https://api.beta.unosap.com/v1/send \
  -H "Authorization: Bearer sk_live_ses_..." \
  -d '{"to": "2348012345678", "type": "document", "mediaUrl": "https://example.com/file.pdf", "fileName": "report.pdf"}'

Interactive buttons

curl -X POST https://api.beta.unosap.com/v1/send \
  -H "Authorization: Bearer sk_live_ses_..." \
  -d '{"to": "2348012345678", "type": "buttons", "text": "Confirm?", "buttons": [{"id": "yes", "label": "Yes"}, {"id": "no", "label": "No"}]}'

List / menu

curl -X POST https://api.beta.unosap.com/v1/send \
  -H "Authorization: Bearer sk_live_ses_..." \
  -d '{"to": "2348012345678", "type": "list", "text": "Choose", "listButtonText": "Select", "sections": [{"title": "Dept", "rows": [{"id": "a", "title": "Support"}]}]}'

Location

curl -X POST https://api.beta.unosap.com/v1/send \
  -H "Authorization: Bearer sk_live_ses_..." \
  -d '{"to": "2348012345678", "type": "location", "latitude": 6.5244, "longitude": 3.3792, "locationName": "Lagos"}'
POST/v1/sessions/:id/send

Send a message via a specific session using a master key. Same body shape as /send.

curl -X POST https://api.beta.unosap.com/v1/sessions/f496492d-.../send \
  -H "Authorization: Bearer sk_live_master_..." \
  -H "Content-Type: application/json" \
  -d '{"to": "2348012345678", "type": "text", "text": "Hello from master key!"}'

Media Upload

Upload files to Uno SAP and receive a hosted URL to use in mediaUrl fields when sending image, video, audio, and document messages.

POST/v1/media/upload

Upload a file using multipart/form-data. Returns a hosted URL valid for use in message payloads.

curl -X POST https://api.beta.unosap.com/v1/media/upload \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@/path/to/photo.jpg"
{ "url": "https://media.unosap.com/uploads/abc123/photo.jpg" }

File size limits

Images

5 MB

image/jpeg, image/png, image/webp

Video

16 MB

video/mp4, video/3gpp

Audio

10 MB

audio/mpeg, audio/ogg, audio/mp4

Documents

100 MB

PDF, DOCX, XLSX, and more

Session & Health

These endpoints use a session-scoped key. The session is determined automatically — no ID in the URL.

GET/v1/session

Get your session's details, status, and phone number.

curl https://api.beta.unosap.com/v1/session \
  -H "Authorization: Bearer sk_live_ses_..."
{
  "id": "f496492d-...",
  "displayName": "Support Line",
  "phone": "2348012345678",
  "status": "CONNECTED",
  "healthScore": 100,
  "webhooksEnabled": true
}
GET/v1/health

Get your session's health score and detail.

curl https://api.beta.unosap.com/v1/health \
  -H "Authorization: Bearer sk_live_ses_..."

Message History

GET/v1/messages?contactPhone=2348012345678

Get outbound messages sent to a phone number. Paginated — 50 per page.

curl "https://api.beta.unosap.com/v1/messages?contactPhone=2348012345678&page=1&limit=50" \
  -H "Authorization: Bearer sk_live_ses_..."
{
  "messages": [{
    "id": "msg_abc", "contactPhone": "2348012345678",
    "direction": "outbound", "body": "Hello!",
    "type": "text", "status": "delivered",
    "timestamp": "2026-05-28T10:30:00Z"
  }],
  "total": 142, "page": 1, "limit": 50
}

Webhooks

Receive real-time events at your server. Configure webhook URLs from the API — each session can have multiple webhooks with different event filters. Webhooks can also be managed per-session from the dashboard.

POST/v1/webhooks

Create a webhook. Secret is auto-generated if not provided.

curl -X POST https://api.beta.unosap.com/v1/webhooks \
  -H "Authorization: Bearer sk_live_ses_..." \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-server.com/hook", "events": ["message.received"], "secret": "my-secret"}'
GET/v1/webhooks

List all your webhooks.

curl https://api.beta.unosap.com/v1/webhooks \
  -H "Authorization: Bearer sk_live_ses_..."
PATCH/v1/webhooks/:webhookId

Update a webhook's URL, events, or enable/disable it.

curl -X PATCH https://api.beta.unosap.com/v1/webhooks/wh_abc \
  -H "Authorization: Bearer sk_live_ses_..." \
  -d '{"enabled": false}'
DELETE/v1/webhooks/:webhookId

Delete a webhook.

curl -X DELETE https://api.beta.unosap.com/v1/webhooks/wh_abc \
  -H "Authorization: Bearer sk_live_ses_..."
POST/v1/webhooks/:webhookId/test

Send a test ping event to the webhook URL to verify delivery.

curl -X POST https://api.beta.unosap.com/v1/webhooks/wh_abc/test \
  -H "Authorization: Bearer sk_live_ses_..."
GET/v1/webhooks/:webhookId/deliveries

Get recent delivery attempts and their response status for a webhook.

curl https://api.beta.unosap.com/v1/webhooks/wh_abc/deliveries \
  -H "Authorization: Bearer sk_live_ses_..."

Event payload

POST https://your-server.com/hook
X-Uno-Signature: a1b2c3d4e5f6...

{
  "event": "message.received",
  "tenantId": "tenant_abc",
  "sessionId": "f496492d-...",
  "timestamp": 1716894200000,
  "data": { "messages": [{ "key": {...}, "message": {...} }] }
}

Verify signatures (Node.js)

const crypto = require('crypto');

app.post('/hook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-uno-signature'];
  const expected = crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');

  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    return res.status(401).end();
  }
  res.status(200).end();
  processEvent(JSON.parse(req.body));
});

Event types

message.received

Inbound message from a user.

message.sent

Your outbound message was acknowledged.

message.delivered

Your message reached the recipient's device.

message.read

The recipient opened your message.

message.updated

A message was edited.

message.deleted

A message was deleted or revoked.

message.reaction

A reaction emoji was added/removed.

session.connected

Your session connected.

session.disconnected

Your session disconnected.

session.banned

Session was banned.

session.qr_updated

New QR code generated.

chats.upsert

Chat created or updated.

chats.update

Chat settings changed.

chats.delete

Chat deleted.

groups.upsert

Group created or number added.

groups.update

Group metadata changed.

group-participants.update

Participant joined/left/promoted.

call.received

WhatsApp call detected.

  • Respond HTTP 200 within 60 seconds. Process async.
  • Always verify signatures using the X-Uno-Signature header with constant-time comparison.
  • Be idempotent — events may be delivered more than once.
  • Don't crash on unknown events — log and continue.
Ready to ship?

Get your API key from a session, pick your language, and start sending.

View Sessions