Skip to content

REST API Reference

Wappa provides a comprehensive REST API for sending WhatsApp messages and managing user state handlers. All endpoints are automatically documented with OpenAPI/Swagger at /docs when running your Wappa application.

API Base URL

All endpoints are prefixed with /api/whatsapp by default. If you're running locally, the base URL would be http://localhost:8000/api/whatsapp.

Authentication

WhatsApp API endpoints require proper credentials configured in your Wappa application. These are set when initializing your Wappa instance:

app = Wappa(
    whatsapp_token="your_whatsapp_token",
    whatsapp_phone_id="your_phone_id",
    whatsapp_business_id="your_business_id"
)

Response Format

All successful responses follow this pattern:

{
  "message_id": "wamid.xxx",
  "recipient": "+1234567890",
  "status": "sent"
}

Error responses include detailed error information:

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

Text Messages

Send Text Message

Send a simple text message to a WhatsApp user.

POST /api/whatsapp/messages/send-text
{
  "recipient": "+1234567890",
  "text": "Hello! Welcome to our service.",
  "reply_to_message_id": "wamid.xxx"  // Optional
}
{
  "message_id": "wamid.HBgNMTIzNDU2Nzg5MABCAA==",
  "recipient": "+1234567890",
  "status": "sent"
}
import httpx

async with httpx.AsyncClient() as client:
    response = await client.post(
        "http://localhost:8000/api/whatsapp/messages/send-text",
        json={
            "recipient": "+1234567890",
            "text": "Hello from Wappa!"
        }
    )
    print(response.json())

Media Messages

Send Image Message

Send an image with an optional caption.

POST /api/whatsapp/media/send-image
{
  "recipient": "+1234567890",
  "media_source": "https://example.com/image.jpg",
  "caption": "Check out this image!",
  "description": "Product catalog showing winter collection items with prices",
  "reply_to_message_id": "wamid.xxx"  // Optional
}
{
  "message_id": "wamid.HBgNMTIzNDU2Nzg5MABCAA==",
  "recipient": "+1234567890",
  "status": "sent"
}
response = await client.post(
    "http://localhost:8000/api/whatsapp/media/send-image",
    json={
        "recipient": "+1234567890",
        "media_source": "https://example.com/product.jpg",
        "caption": "Here's your product catalog!",
        "description": "Product catalog page showing seasonal items"
    }
)

AI Context with Description Field

The description field (max 2048 chars) is NOT sent to WhatsApp. It's stored for AI agent context to understand what media was sent to the user. This helps AI assistants provide better conversational experiences.

Field Details: - media_source - Either a URL or WhatsApp media ID - caption - User-visible text (max 1024 chars) - description - AI context only, not sent to WhatsApp (max 2048 chars) - reply_to_message_id - Optional message ID to reply to

Supported formats: JPEG, PNG (max 5MB)


Send Video Message

Send a video with an optional caption.

POST /api/whatsapp/media/send-video
{
  "recipient": "+1234567890",
  "media_source": "https://example.com/video.mp4",
  "caption": "Product demo video",
  "description": "5-minute product demonstration showing key features",
  "reply_to_message_id": "wamid.xxx"  // Optional
}

Supported formats: MP4, 3GP (max 16MB) Codec requirements: H.264 video, AAC audio


Send Audio Message

Send an audio file or voice message.

POST /api/whatsapp/media/send-audio
{
  "recipient": "+1234567890",
  "media_source": "https://example.com/audio.mp3",
  "description": "Customer service callback recording about order #12345",
  "reply_to_message_id": "wamid.xxx"  // Optional
}

No Caption for Audio

Audio messages do not support captions. Use the description field for AI context.

Supported formats: AAC, MP3, MP4, AMR, OGG (max 16MB)


Send Document Message

Send a document file with optional caption and filename.

POST /api/whatsapp/media/send-document
{
  "recipient": "+1234567890",
  "media_source": "https://example.com/invoice.pdf",
  "filename": "Invoice_2025_01.pdf",
  "caption": "Your invoice for January 2025",
  "description": "Monthly invoice showing itemized charges and payment details",
  "reply_to_message_id": "wamid.xxx"  // Optional
}

Supported formats: TXT, PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX (max 100MB)


Send Sticker Message

Send a sticker to a user.

POST /api/whatsapp/media/send-sticker
{
  "recipient": "+1234567890",
  "media_source": "https://example.com/sticker.webp",
  "description": "Thumbs up approval sticker",
  "reply_to_message_id": "wamid.xxx"  // Optional
}

No Caption for Stickers

Stickers do not support captions. Use the description field for AI context.

Supported formats: WebP only Size limits: Static: 100KB, Animated: 500KB


Interactive Messages

Send Interactive Buttons

Send a message with up to 3 action buttons.

POST /api/whatsapp/interactive/send-buttons
{
  "recipient": "+1234567890",
  "body_text": "Would you like to continue?",
  "buttons": [
    {
      "button_id": "btn_yes",
      "title": "Yes, continue"
    },
    {
      "button_id": "btn_no",
      "title": "No, cancel"
    }
  ],
  "header_text": "Confirmation Required",  // Optional
  "footer_text": "Reply with your choice"    // Optional
}
{
  "message_id": "wamid.HBgNMTIzNDU2Nzg5MABCAA==",
  "recipient": "+1234567890",
  "status": "sent"
}

Limits: Max 3 buttons, button titles max 20 characters


Send Interactive List

Send a message with a list of selectable items (up to 10 items).

POST /api/whatsapp/interactive/send-list
{
  "recipient": "+1234567890",
  "body_text": "Select a product category:",
  "button_text": "View Options",
  "sections": [
    {
      "title": "Electronics",
      "rows": [
        {
          "row_id": "electronics_phones",
          "title": "Phones",
          "description": "Latest smartphones"
        },
        {
          "row_id": "electronics_laptops",
          "title": "Laptops",
          "description": "Business laptops"
        }
      ]
    },
    {
      "title": "Clothing",
      "rows": [
        {
          "row_id": "clothing_mens",
          "title": "Men's Wear",
          "description": "Men's fashion"
        }
      ]
    }
  ],
  "header_text": "Product Catalog",  // Optional
  "footer_text": "Select to learn more"  // Optional
}

Limits: Max 10 items across all sections, max 24 characters per title


Template Messages

Send Text Template

Send a pre-approved WhatsApp template with text content.

POST /api/whatsapp/templates/send-text
{
  "recipient": "+1234567890",
  "template_name": "appointment_reminder",
  "language_code": "en",
  "components": [
    {
      "type": "body",
      "parameters": [
        {
          "type": "text",
          "text": "John Doe"
        },
        {
          "type": "text",
          "text": "January 15, 2025"
        }
      ]
    }
  ],
  "state_config": {
    "state_value": "reschedule_flow",
    "ttl_seconds": 3600,
    "initial_context": {
      "appointment_id": "12345"
    }
  }
}

Template State Management

Use state_config to automatically assign a state handler after the template is sent. This enables workflow routing when users respond.


Send Media Template

Send a template with media header (image, video, or document).

POST /api/whatsapp/templates/send-media
{
  "recipient": "+1234567890",
  "template_name": "product_promo",
  "language_code": "en",
  "header_media_type": "image",
  "header_media_source": "https://example.com/promo.jpg",
  "components": [
    {
      "type": "body",
      "parameters": [
        {
          "type": "text",
          "text": "50% Off"
        }
      ]
    }
  ]
}

Supported header types: image, video, document


State Handler Management

State handlers allow you to route user responses to specific event handlers based on their current state. This is perfect for multi-step workflows and automation.

New Feature

State handler API is message-agnostic - use it after sending ANY message type (text, media, templates, interactive messages).

Set State Handler

Assign a state handler to a user for workflow routing.

POST /api/whatsapp/state-handlers/set
{
  "recipient": "+1234567890",
  "handler_config": {
    "handler_value": "reschedule_flow",
    "ttl_seconds": 3600,
    "initial_context": {
      "appointment_id": "12345",
      "original_time": "2025-01-15T10:00:00Z",
      "max_reschedules": 3
    }
  }
}
{
  "success": true,
  "message": "State handler assigned successfully",
  "recipient": "+1234567890",
  "handler_value": "reschedule_flow",
  "cache_key": "api-handler-reschedule_flow",
  "expires_at": "2025-01-12T17:30:00Z"
}
# Step 1: Send a message (any type)
await client.post(
    "http://localhost:8000/api/whatsapp/media/send-image",
    json={
        "recipient": "+1234567890",
        "media_source": "https://example.com/appointment.jpg",
        "caption": "Your appointment details"
    }
)

# Step 2: Assign state handler via automation
await client.post(
    "http://localhost:8000/api/whatsapp/state-handlers/set",
    json={
        "recipient": "+1234567890",
        "handler_config": {
            "handler_value": "reschedule_flow",
            "ttl_seconds": 3600,
            "initial_context": {
                "appointment_id": "12345"
            }
        }
    }
)

# Now when user responds, your event dispatcher will route to the handler

Use Cases: - Multi-step workflows - Guide users through forms, surveys, or onboarding - Appointment management - Handle reschedules, cancellations, confirmations - Order processing - Track order status, modifications, and support requests - Automation integration - Route responses after external events or triggers

Parameters: - handler_value - Unique identifier for the state handler (1-100 chars) - ttl_seconds - Time-to-live for the handler state (60-86400 seconds = 1 min to 24 hours) - initial_context - Optional context data for the handler

Cache Key Pattern: api-handler-{handler_value}


Get State Handler

Retrieve the current state handler assigned to a user.

GET /api/whatsapp/state-handlers/get/{recipient}/{handler_value}
GET /api/whatsapp/state-handlers/get/+1234567890/reschedule_flow
{
  "success": true,
  "recipient": "+1234567890",
  "handler_value": "reschedule_flow",
  "state": {
    "handler_value": "reschedule_flow",
    "recipient": "+1234567890",
    "assigned_at": "2025-01-12T16:30:00Z",
    "expires_at": "2025-01-12T17:30:00Z",
    "appointment_id": "12345",
    "original_time": "2025-01-15T10:00:00Z",
    "max_reschedules": 3
  }
}

Delete State Handler

Remove a state handler assignment from a user.

DELETE /api/whatsapp/state-handlers/delete/{recipient}/{handler_value}
DELETE /api/whatsapp/state-handlers/delete/+1234567890/reschedule_flow
{
  "success": true,
  "message": "Handler state deleted successfully",
  "recipient": "+1234567890",
  "handler_value": "reschedule_flow"
}

Common Patterns

Pattern 1: Send Message + Assign Handler

Perfect for automation workflows where you need to route user responses.

import httpx

async def send_with_handler(recipient: str, image_url: str):
    async with httpx.AsyncClient() as client:
        # Step 1: Send message
        response = await client.post(
            "http://localhost:8000/api/whatsapp/media/send-image",
            json={
                "recipient": recipient,
                "media_source": image_url,
                "caption": "Please confirm your appointment",
                "description": "Appointment confirmation card with date and time"
            }
        )

        # Step 2: Assign state handler
        await client.post(
            "http://localhost:8000/api/whatsapp/state-handlers/set",
            json={
                "recipient": recipient,
                "handler_config": {
                    "handler_value": "appointment_confirmation",
                    "ttl_seconds": 7200,  # 2 hours
                    "initial_context": {
                        "appointment_id": "12345",
                        "can_reschedule": True
                    }
                }
            }
        )

        return response.json()

Pattern 2: Template with Auto State

Use template state config for automatic handler assignment.

async def send_reminder_with_state(recipient: str, name: str, date: str):
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "http://localhost:8000/api/whatsapp/templates/send-text",
            json={
                "recipient": recipient,
                "template_name": "appointment_reminder",
                "language_code": "en",
                "components": [
                    {
                        "type": "body",
                        "parameters": [
                            {"type": "text", "text": name},
                            {"type": "text", "text": date}
                        ]
                    }
                ],
                "state_config": {
                    "state_value": "reschedule_flow",
                    "ttl_seconds": 3600,
                    "initial_context": {
                        "appointment_id": "12345",
                        "original_time": date
                    }
                }
            }
        )
        return response.json()

Pattern 3: AI Context with Media

Provide rich context for AI agents handling conversations.

async def send_product_with_ai_context(recipient: str, product_id: str):
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "http://localhost:8000/api/whatsapp/media/send-image",
            json={
                "recipient": recipient,
                "media_source": f"https://example.com/products/{product_id}.jpg",
                "caption": "Check out this product!",
                "description": (
                    f"Product ID: {product_id}, Winter Collection 2025, "
                    "Price: $49.99, Available in sizes S-XL, "
                    "Rating: 4.5/5 stars, Best seller in electronics category"
                )
            }
        )
        return response.json()

Error Handling

All endpoints return standard HTTP status codes:

Status Code Meaning
200 Success
201 Created (for POST /state-handlers/set)
400 Bad Request - Invalid input parameters
401 Unauthorized - Invalid WhatsApp credentials
404 Not Found - Resource doesn't exist
429 Rate Limited - Too many requests
500 Internal Server Error - Server-side issue

Example error response:

{
  "detail": "Failed to send message: Invalid phone number format"
}

Rate Limits

WhatsApp Business API has rate limits based on your tier:

  • Tier 1: 1,000 messages per day
  • Tier 2: 10,000 messages per day
  • Tier 3: 100,000 messages per day
  • Unlimited: No daily limit

Rate Limiting

Exceeding rate limits will result in 429 Too Many Requests responses. Implement exponential backoff for retries.


Interactive API Documentation

Wappa automatically generates interactive API documentation using FastAPI's built-in Swagger UI:

# Access at http://localhost:8000/docs

Features: - ✅ Try endpoints directly from the browser - ✅ View request/response schemas - ✅ See all available parameters - ✅ Copy curl commands - ✅ Download OpenAPI spec


Next Steps

Sending messages from code? → Use the Messaging API for direct Python integration

Building event handlers? → Check Event Handlers to handle incoming messages

Managing state? → Explore Cache API for state management patterns

Need webhooks? → Reference Webhooks API for webhook data structures


Build powerful conversational experiences with Wappa's REST API! 🚀