WatConnexio

Send your first WhatsApp message

Connect a device, make an API request, then check delivery. Keep your API key on your server.

Before your first request

  1. Sign in and connect your WhatsApp device from Overview.
  2. Get an active key from API Keys and store it in your server environment.
  3. List your devices and choose a connected, active device ID.
  4. Send to a number you control. Sending uses your message allowance.
  5. Use the returned message ID to check delivery and confirm receipt on the phone.

For OTP messages, your application generates, expires, rate-limits, and verifies the code. WatConnexio transports the message.

# WatConnexio API Documentation

Base URL: https://api-wat.tryconnexio.com

## Authentication

Include this header on every request:

```http
Authorization: Bearer YOUR_API_KEY
```

Keep API keys private. Rotating a key immediately invalidates the previous key.
All examples use placeholders, not live credentials or account data.

## Response structure

All endpoints below return JSON with these fields:

| Field | Type | Meaning |
| --- | --- | --- |
| code | number | HTTP status code, matching the response status |
| message | string | Human-readable result or error |
| data | object, array, or null | Useful result data; null on errors |

## Get devices

GET /whatsapp/devices

No request body or query parameters. Returns devices belonging to the authenticated account.

```json
{
  "code": 200,
  "message": "Devices retrieved.",
  "data": [
    {
      "id": "DEVICE_ID",
      "name": "Work phone",
      "phoneNumber": "2348012345678",
      "status": "connected",
      "isActive": true,
      "lastSeen": "2026-01-01T12:00:00.000Z"
    }
  ]
}
```

An account with no devices receives an empty data array.
Device status is connected, connecting, or disconnected.
phoneNumber and lastSeen can be null.
A Safari Com arrival guide also includes "agentRole": "safaricom". Ordinary send devices omit that field.

## Get device by ID

GET /whatsapp/devices/:deviceId

Replace :deviceId with a device ID from the list endpoint.
Returns HTTP 200 with one device object in data and message "Device retrieved.".
Returns HTTP 404 if the device is unavailable to the authenticated account.

## Send message

POST /whatsapp/send-message

Content-Type: application/json

```json
{
  "deviceId": "DEVICE_ID",
  "phone": "2348012345678",
  "message": "Hello from WatConnexio!"
}
```

deviceId, phone, and message are required. Use an international recipient number
including its country code. The device must be connected and active.

Successful send response (also used for file URLs and uploads):

```json
{
  "code": 201,
  "message": "Message accepted. Delivery is not yet confirmed.",
  "data": {
    "messageId": "MESSAGE_ID",
    "deviceId": "DEVICE_ID",
    "status": "accepted"
  }
}
```

Acceptance is not a delivery receipt. Use the delivery-status endpoint below.

## Send file by URL

POST /whatsapp/send-file

Content-Type: application/json

```json
{
  "deviceId": "DEVICE_ID",
  "phone": "2348012345678",
  "fileUrl": "https://example.com/document.pdf",
  "caption": "Your document"
}
```

deviceId, phone, and fileUrl are required; caption is optional.
The file URL must be publicly accessible to the backend.
The 2 MB multipart upload limit below does not apply to this URL endpoint.

## Upload a document

POST /whatsapp/send-upload

Content-Type: multipart/form-data

| Form field | Required | Meaning |
| --- | --- | --- |
| deviceId | Yes | Device ID |
| phone | Yes | International number with 7-15 digits, optional leading + |
| file | Yes | One non-empty document; maximum 2,097,152 bytes (2 MB) |
| caption | No | Document caption |

Let the HTTP client generate the multipart boundary. Do not manually set the
Content-Type header when using browser FormData.

Example using a POSIX shell:

```sh
curl -X POST 'https://api-wat.tryconnexio.com/whatsapp/send-upload' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Idempotency-Key: YOUR_UNIQUE_REQUEST_ID' \
  -F 'deviceId=DEVICE_ID' \
  -F 'phone=2348012345678' \
  --form-string 'caption=Your document' \
  -F 'file=@/path/to/document.pdf'
```

Oversized uploads return HTTP 413:

```json
{
  "code": 413,
  "message": "File is too large. Maximum upload size is 2 MB (2,097,152 bytes).",
  "data": null
}
```

## Check delivery status

GET /whatsapp/sessions/:deviceId/messages/:messageId/status

Use the deviceId and messageId from the send response. No request body.

```json
{
  "code": 200,
  "message": "Delivery status retrieved.",
  "data": {
    "messageId": "MESSAGE_ID",
    "status": "delivered",
    "updatedAt": "2026-01-01T12:00:00.000Z"
  }
}
```

Possible statuses: pending, server_ack, delivered, read, played, error, unknown.
updatedAt may be null. Receipt history is in memory, expires after 24 hours,
and is lost when the backend restarts. Unknown does not prove delivery failure.

## Safe retries

For every send endpoint, optionally include Idempotency-Key (maximum 200 characters).
Use a unique key for each intended message. Retrying the identical request with
the same key replays a completed result instead of sending again.
For uploads, retain identical file contents, filename, MIME type, and form values.

HTTP 409 indicates a conflicting payload or a pending/uncertain outcome.
After a timeout or uncertain result, do not switch to a new key to bypass protection:
that could send a duplicate message. Reservations currently have no automatic expiry.

## Errors

| HTTP code | Meaning |
| --- | --- |
| 400 | Missing or invalid request fields, or empty upload |
| 401 | Authentication required or invalid credentials |
| 403 | Plan or usage limit reached |
| 404 | Device not found or unavailable to the account |
| 409 | Idempotency conflict or uncertain send outcome |
| 413 | Upload exceeds 2 MB |
| 429 | Rate limit reached |
| 500 | Request could not be completed; a send outcome may be uncertain |

```json
{
  "code": 404,
  "message": "Device not found",
  "data": null
}
```

## Sandbox modes

Simulation validates locally and displays example responses. It does not send
messages, charge usage, or verify authentication or delivery.
Live API mode calls production endpoints. Live sends reach actual recipients
and count toward account usage. Read-only device queries do not send messages.