The unified inbox stores every WhatsApp conversation across your connected sessions. Authorize these routes with X-API-Key (messages:read to list, messages:send to reply).

Inbound and outbound messages are synced automatically when a session is connected. Threads are scoped to your workspace. Members see conversations they are allowed to access; owners and admins see the full inbox.

How the inbox works

Each thread is one contact talking to one WhatsApp session. When a message arrives or is sent, ActiWAPI upserts the thread, stores the message, and pushes a Socket.io update so the dashboard does not need to poll.

Phone numbers are stored in canonical form (digits with country code, mapped to @s.whatsapp.net). Linked-device LID identifiers are resolved to the phone JID whenever possible so inbound and outbound history stay on the same thread.

  • List threads with search, session filter, and status (open / resolved).
  • Load paginated messages for a thread, then send a text or media reply.
  • Assign a teammate or resolve the thread when the conversation is done.

Replying with media

Upload a file with POST /api/chats/upload first. The response includes a media URL (and path). Pass that URL on POST /api/chats/{threadId}/send together with messageType (image, document, audio, video) and optional fileName / mimetype.

Authorize inbox calls with X-API-Key (messages:read to list, messages:send to reply). Outbound sends from the Messages API land in the same inbox.

GET/api/chats

List threads

Paginated inbox threads for the authenticated workspace, newest activity first.

URL: https://api.actiwapi.com/api/chats

Auth: API Key

Headers

HeaderValueRequired
X-API-Key{apiKey}Yes
Content-Typeapplication/jsonYes*

Query parameters

  • page — Page number (default 1)
  • limit — Items per page (default 20)
  • search — Filter by contact name or phone
  • sessionId — Limit to one WhatsApp session UUID
  • status — open, resolved, or omit for all

Code examples

curl -X GET "https://api.actiwapi.com/api/chats" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: {apiKey}"

Response example200

{
  "success": true,
  "data": [{
    "id": "uuid",
    "sessionId": "uuid",
    "remoteJid": "919876543210@s.whatsapp.net",
    "contactName": "Priya",
    "phone": "919876543210",
    "lastMessage": "Thanks, that worked",
    "unreadCount": 1,
    "status": "open",
    "assignedUserId": null,
    "updatedAt": "2026-09-03T12:00:00.000Z"
  }],
  "pagination": { "page": 1, "limit": 20, "total": 12, "pages": 1 }
}

Try in Swagger UI

GET/api/chats/{threadId}/messages

Get thread messages

Paginated message history for a single conversation.

URL: https://api.actiwapi.com/api/chats/{threadId}/messages

Auth: API Key

Headers

HeaderValueRequired
X-API-Key{apiKey}Yes
Content-Typeapplication/jsonYes*

Path parameters

  • threadId — Inbox thread UUID

Query parameters

  • page — Page number
  • limit — Messages per page

Code examples

curl -X GET "https://api.actiwapi.com/api/chats/{threadId}/messages" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: {apiKey}"

Response example200

{
  "success": true,
  "data": [{
    "id": "uuid",
    "direction": "inbound",
    "messageType": "text",
    "content": "Hi, I need help",
    "status": "delivered",
    "createdAt": "2026-09-03T12:00:00.000Z"
  }],
  "pagination": { "page": 1, "limit": 50, "total": 8, "pages": 1 }
}

Try in Swagger UI

POST/api/chats/upload

Upload inbox media

Upload a file for use in an inbox reply. Send as multipart/form-data.

URL: https://api.actiwapi.com/api/chats/upload

Auth: API Key

Headers

HeaderValueRequired
X-API-Key{apiKey}Yes
Content-Typeapplication/jsonIf JSON

Request example

Form field: file (binary)

Code examples

curl -X POST "https://api.actiwapi.com/api/chats/upload" \
  -H "Content-Type: multipart/form-data" \
  -H "X-API-Key: {apiKey}"
  -d 'Form field: file (binary)'

Response example200

{
  "success": true,
  "data": {
    "url": "/uploads/...",
    "path": "uploads/...",
    "fileName": "photo.jpg",
    "mimetype": "image/jpeg"
  }
}

Try in Swagger UI

POST/api/chats/{threadId}/send

Send a reply

Reply on an existing thread. Provide text and/or mediaUrl.

URL: https://api.actiwapi.com/api/chats/{threadId}/send

Auth: API Key

Headers

HeaderValueRequired
X-API-Key{apiKey}Yes
Content-Typeapplication/jsonYes*

Path parameters

  • threadId — Inbox thread UUID

Request example

{
  "text": "We can help with that.",
  "mediaUrl": null,
  "messageType": "text",
  "fileName": null,
  "mimetype": null
}

Code examples

curl -X POST "https://api.actiwapi.com/api/chats/{threadId}/send" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: {apiKey}"
  -d '{  "text": "We can help with that.",  "mediaUrl": null,  "messageType": "text",  "fileName": null,  "mimetype": null}'

Response example200

{
  "success": true,
  "data": { "id": "uuid", "status": "queued", "direction": "outbound" }
}

Try in Swagger UI

POST/api/chats/{threadId}/assign

Assign an agent

Assign the thread to a workspace user. Pass userId null to unassign.

URL: https://api.actiwapi.com/api/chats/{threadId}/assign

Auth: API Key

Headers

HeaderValueRequired
X-API-Key{apiKey}Yes
Content-Typeapplication/jsonYes*

Path parameters

  • threadId — Inbox thread UUID

Request example

{ "userId": "uuid" }

Code examples

curl -X POST "https://api.actiwapi.com/api/chats/{threadId}/assign" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: {apiKey}"
  -d '{ "userId": "uuid" }'

Response example200

{ "success": true, "data": { "id": "uuid", "assignedUserId": "uuid" } }

Try in Swagger UI

POST/api/chats/{threadId}/resolve

Resolve a thread

Mark the conversation resolved. New inbound messages typically reopen it.

URL: https://api.actiwapi.com/api/chats/{threadId}/resolve

Auth: API Key

Headers

HeaderValueRequired
X-API-Key{apiKey}Yes
Content-Typeapplication/jsonYes*

Path parameters

  • threadId — Inbox thread UUID

Code examples

curl -X POST "https://api.actiwapi.com/api/chats/{threadId}/resolve" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: {apiKey}"

Response example200

{ "success": true, "data": { "id": "uuid", "status": "resolved" } }

Try in Swagger UI

Error codes

Failed requests return a JSON envelope with success: false and a human-readable message.

{
  "success": false,
  "message": "Validation failed",
  "errors": {
    "phone": "Valid phone number is required"
  }
}
HTTPCodeDescription
400VALIDATION_ERRORRequest body or query failed validation.
401UNAUTHORIZEDMissing or invalid JWT / API key.
403FORBIDDENAuthenticated but lacking permission or entitlement.
403SUBSCRIPTION_INACTIVEAction not allowed on the current plan (including Free after trial). Upgrade or wait for entitlements.
403LIMIT_EXCEEDEDPlan limit reached (sessions, messages, API requests, etc.).
404NOT_FOUNDResource does not exist or is not in your account.
409CONFLICTDuplicate resource or invalid state transition.
429RATE_LIMITEDToo many requests; retry after backoff.
500INTERNAL_ERRORUnexpected server error.
502WHATSAPP_UNAVAILABLEWhatsApp session disconnected or provider error.