Skip to content

WhatsApp Lite API Guide

Complete documentation for the WhatsApp Lite edge functions, with internal logic and sample curl commands for all use cases. WhatsApp Lite runs on Appgain (api.appgain.io) with QR-code pairing.

Table of Contents

  1. whatsapp-lite-send - Sending Messages
  2. Direct AppGain API - curl for all calling cases
  3. Curl Examples (Supabase edge function)
  4. appgain-whatsapp-webhook - Receiving Messages
  5. Common Use Cases

whatsapp-lite-send - Sending Messages

Internal Logic Flow

1. Request Validation
 ├─ Validates JSON payload
 ├─ Ensures required fields: `to`, `message`
 ├─ Validates message length (max 4096 chars)
 └─ Ensures `organizationId` is provided

2. Phone Number Processing
 ├─ Cleans phone number (removes @s.whatsapp.net)
 └─ Logs both original and cleaned versions

3. Organization Lookup
 ├─ Look up org by `organizationId`

4. Get AppGain Credentials
 ├─ Extract `appgain_api_key` from org settings

5. Send via AppGain API
 ├─ POST to https://notify.appgain.io/{organizationId}/send
 ├─ Headers: appapikey, Content-Type
 └─ Body: UOWHATSAPP payload with cleaned phone number

6. Contact Management
 ├─ Find existing contact by phone number (via shared utility)
 ├─ If not found, create with `contactName` or "Unknown Contact"
 └─ Store multiple phone number variations for better matching

7. Channel Account Management
 ├─ Look up ALL active channel accounts for organization
 ├─ Use the FIRST (most recent) one found
 └─ If none exist, create new channel account

8. Conversation Management
 ├─ If `conversationId` provided → use it directly
 ├─ If not provided:
 │ ├─ Search for existing OPEN conversation for contact + channel
 │ ├─ If found → use existing conversation ID
 │ └─ If not found → create new conversation
 └─ Update `last_message_at` timestamp

9. Message Storage
 ├─ Insert message with direction: "OUTBOUND"
 ├─ Set status: "SENT"
 ├─ Store `external_id` from AppGain response
 ├─ If `from` provided → add to metadata as `sender_name`
 └─ Link to conversation and contact

10. Return Response
 ├─ success: true/false
 ├─ result: AppGain API response
 ├─ conversationId
 ├─ contactId
 └─ debug info

API Endpoint

POST https://YOUR_SUPABASE_URL/functions/v1/whatsapp-lite-send

Required Headers

Authorization: Bearer YOUR_ANON_KEY
Content-Type: application/json

Request Parameters

Field Type Required Description
to string ✅ Yes Recipient phone number (supports 201001383533@s.whatsapp.net format)
message string ✅ Yes Message content (max 4096 characters)
organizationId string ✅ Yes Your ConnectGain organization UUID
conversationId string ❌ No Use existing conversation ID instead of creating/finding one
contactName string ❌ No Contact name when creating new contact
from string ❌ No Sender name for UI display (stored in metadata)

Response

Success Response (200 OK):

{
 "success": true,
 "result": {
 "status": "success",
 "message": "successfully sent"
 },
 "conversationId": "uuid-of-conversation",
 "contactId": "uuid-of-contact",
 "debug": {
 "hasChannelAccount": false,
 "hasConversationId": true,
 "hasContactId": true
 }
}

Error Response (400/404/500):

{
 "error": "Error message describing what went wrong"
}


Direct AppGain API - curl for all calling cases

These examples call the AppGain notify API directly (https://notify.appgain.io/{organizationId}/send). Use your organizationId and AppGain API key from channel settings.

  • Base: POST https://notify.appgain.io/{organizationId}/send
  • Headers: appapikey: YOUR_APPGAIN_API_KEY, Content-Type: application/json
  • Body: JSON with top-level key UOWHATSAPP. Phone numbers must be cleaned (no @s.whatsapp.net).

AppGain case 1: Text only

curl -X POST "https://notify.appgain.io/your-org-uuid-here/send" \
 -H "appapikey: YOUR_APPGAIN_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "UOWHATSAPP": {
 "random_string": 0,
 "receivers": [{ "mobileNum": "201001383533" }],
 "message": "Hello, this is a text-only message"
 }
 }'

AppGain case 2: Image only (no caption)

curl -X POST "https://notify.appgain.io/your-org-uuid-here/send" \
 -H "appapikey: YOUR_APPGAIN_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "UOWHATSAPP": {
 "random_string": 0,
 "receivers": [{ "mobileNum": "201001383533" }],
 "imageUrl": "https://example.com/image.jpg"
 }
 }'

AppGain case 3: Image with caption

curl -X POST "https://notify.appgain.io/your-org-uuid-here/send" \
 -H "appapikey: YOUR_APPGAIN_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "UOWHATSAPP": {
 "random_string": 0,
 "receivers": [{ "mobileNum": "201001383533" }],
 "imageUrl": "https://example.com/image.jpg",
 "message": "Check out this image"
 }
 }'

AppGain case 4: Video

curl -X POST "https://notify.appgain.io/your-org-uuid-here/send" \
 -H "appapikey: YOUR_APPGAIN_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "UOWHATSAPP": {
 "random_string": 0,
 "receivers": [{ "mobileNum": "201001383533" }],
 "message": "Optional caption for video",
 "videoUrl": "https://example.com/video.mp4",
 "imageUrl": ""
 }
 }'

AppGain case 5: Document

curl -X POST "https://notify.appgain.io/your-org-uuid-here/send" \
 -H "appapikey: YOUR_APPGAIN_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "UOWHATSAPP": {
 "random_string": 0,
 "receivers": [{ "mobileNum": "201001383533" }],
 "message": "Optional caption for document",
 "documentUrl": "https://example.com/document.pdf",
 "imageUrl": ""
 }
 }'

AppGain case 6: Multiple receivers (broadcast)

curl -X POST "https://notify.appgain.io/your-org-uuid-here/send" \
 -H "appapikey: YOUR_APPGAIN_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "UOWHATSAPP": {
 "random_string": 0,
 "receivers": [
 { "mobileNum": "201001383533" },
 { "mobileNum": "2015551234567" }
 ],
 "message": "Broadcast message to multiple numbers"
 }
 }'

Note: The whatsapp-lite-send edge function only uses AppGain cases 1–3 (text, image, image+caption). Video and document (cases 4–5) are used by the campaign scheduler; multiple receivers (case 6) are used by campaigns, not by the single-message edge function.

Multi-attachment delivery: When one message carries multiple attachments, the edge function sends one AppGain call per attachment. Two things are needed so all of them are delivered (not just the first):

  • Unique random_string on calls 2..N only. AppGain treats random_string as a per-send de-duplication nonce, so reusing a constant value for a burst to the same receiver makes AppGain drop calls 2..N as duplicate retries. However, AppGain also reflects a non-zero random_string in the delivered message content — sending every call with a unique nonce altered normal chat texts in production (recipients received the typed text with the nonce appended). The edge function therefore sends random_string: 0 on the first/only call (the one carrying the typed text or caption — matching the curl examples above) and a unique value only on the caption-less attachment calls 2..N.
  • Randomized pacing. A randomized ~0.8–2.5 s delay is inserted between consecutive sends so the WhatsApp session doesn't collapse a rapid burst.

Curl Examples (Supabase edge function)

Example 1: Basic Message Using organizationId

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533",
 "message": "Hello, this is a test message",
 "organizationId": "your-org-uuid-here"
 }'

Example 2: Message with Phone Number Including @s.whatsapp.net

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533@s.whatsapp.net",
 "message": "Message with @s.whatsapp.net format",
 "organizationId": "your-org-uuid-here"
 }'

Example 3: Message with Custom Sender Name (from field)

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533",
 "message": "Hello from AIBot!",
 "from": "AIBot"
 }'

Example 4: Message with Contact Name

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533",
 "message": "Hello Mohamed!",
 "contactName": "Mohamed Shaheen"
 }'

Example 5: Complete Example with All Optional Fields

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533@s.whatsapp.net",
 "message": "Hello Mohamed from AIBot!",
 "contactName": "Mohamed Shaheen",
 "from": "AIBot"
 }'

Example 6: Using organizationId

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533",
 "message": "Message using organizationId",
 "organizationId": "your-org-uuid-here"
 }'

Example 7: Send to Existing Conversation

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533",
 "message": "Follow-up message",
 "conversationId": "existing-conversation-uuid"
 }'

Example 8: Send Media (image URL with optional caption)

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533",
 "message": "Check out this image",
 "media_urls": ["https://example.com/image.jpg"]
 }'

Example 9: Cross-Channel Response (e.g. reply via WhatsApp Lite when original was WhatsApp Cloud)

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533",
 "message": "Reply from Lite channel",
 "conversationId": "existing-conversation-uuid",
 "crossChannelResponse": {
 "originalChannelId": "original-channel-account-uuid",
 "originalChannelType": "WHATSAPP_CLOUD",
 "responseChannelId": "whatsapp-lite-channel-account-uuid"
 }
 }'

Note: A cross-channel message is persisted in the conversation belonging to the channel it was actually sent from (the WhatsApp Lite channel's own thread with that contact — found or created atomically), not in the conversationId passed in the request. The response's conversationId field returns the thread the message landed in, and the dashboard uses it to switch the inbox to that conversation after sending. The passed conversationId is still used to resolve the recipient when to is omitted, and is recorded in the message's metadata.cross_channel for traceability.


appgain-whatsapp-webhook - Receiving Messages

Inbound WhatsApp Lite messages arrive through the appgain-whatsapp-webhook edge function. It acknowledges the provider quickly, then (in the background) looks up or creates the contact and conversation, deduplicates the message, re-hosts media in Supabase Storage, and triggers automations. See the webhook system overview for how inbound webhooks are processed.

Common Use Cases

Use Case 1: Send Welcome Message to New Customer

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533",
 "message": "Welcome to our service! How can we help you today?",
 "contactName": "New Customer",
 "from": "Support Team"
 }'

Use Case 2: Send Order Confirmation as AIBot

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533",
 "message": "Your order #12345 has been confirmed. Expected delivery: 3 days.",
 "from": "AIBot"
 }'

Use Case 3: Follow-up Message in Existing Conversation

curl -X POST https://txpaxbxhnvnhsjwwaeoy.supabase.co/functions/v1/whatsapp-lite-send \
 -H "Authorization: Bearer YOUR_ANON_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "to": "201001383533",
 "message": "I wanted to follow up on your inquiry.",
 "conversationId": "existing-conversation-uuid",
 "from": "Agent Sarah"
 }'

Error Handling

Failed requests return the error response format shown in the Response section above, with HTTP status 400 (validation), 404 (organization or credentials not found), or 500 (provider or internal error).

Notes

  1. Phone Number Formats: Both functions automatically handle phone numbers with or without @s.whatsapp.net suffix
  2. Duplicate Prevention: Both functions use the same channel account lookup to prevent duplicate conversations
  3. Contact Matching: Uses multiple phone number variations to find existing contacts
  4. Sender Display: The from field is stored in metadata and can be displayed in the UI as the message sender
  5. Automatic Creation: Both contacts and conversations are automatically created if they don't exist

See also


ConnectGain — omnichannel inbox, CRM & automation for WhatsApp, Messenger, Instagram, Telegram and more. Open the app · Docs home