Skip to content
5 min read

WhatsApp Messaging API

Send and receive WhatsApp messages programmatically outside the Wallin Inbox.

Base URL: {WALLIN_URL}/api/whatsapp

All endpoints require Sanctum authentication (see Authentication) and a valid tenant context.

POST /send-text

Send a text message to a customer.

Request:

curl -X POST https://wallin.example/api/whatsapp/send-text \
  -H "Authorization: Bearer 1|abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "business_account_id": 1,
    "to": "+201001234567",
    "message": "Hello! How can I help?",
    "conversation_id": 42
  }'

Parameters:

Field Type Required Description
business_account_id integer yes ID of the WhatsApp Business Account (ChannelConnection)
to string yes Recipient phone in E.164 format (e.g., +201001234567)
message string yes Message text (max 4,096 characters)
conversation_id integer no Conversation ID to link this message to (creates a record in conversation threads)

Response (200 OK):

{
  "success": true,
  "message_id": 123,
  "whatsapp_message_id": "wamid_abc123xyz"
}

Errors:

400 Bad Request β€” Invalid parameters:

{
  "message": "The to field is required.",
  "errors": {
    "to": ["The to field is required."]
  }
}

401 Unauthorized β€” Missing or invalid token (see Authentication)

403 Forbidden β€” Business account doesn't belong to your organization:

{
  "message": "This action is unauthorized."
}

500 Internal Server Error β€” Send failed (connection error, rate limited by Meta, etc.):

{
  "error": "Failed to send message"
}

POST /send-template

Send a pre-approved template message.

Request:

curl -X POST https://wallin.example/api/whatsapp/send-template \
  -H "Authorization: Bearer 1|abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "business_account_id": 1,
    "to": "+201001234567",
    "template_name": "hello_world",
    "language_code": "en",
    "parameters": ["Ahmad", "ORD-123"],
    "conversation_id": 42
  }'

Parameters:

Field Type Required Description
business_account_id integer yes ID of the WhatsApp Business Account
to string yes Recipient phone in E.164 format
template_name string yes Template name (e.g., hello_world)
language_code string yes Template language (e.g., en, ar)
parameters array no Ordered list of variable values (replaces {{1}}, {{2}}, etc.)
conversation_id integer no Conversation ID for threading

Response (200 OK):

{
  "success": true,
  "message_id": 123,
  "whatsapp_message_id": "wamid_abc123xyz"
}

Errors:

  • 400 Bad Request β€” Template not found or invalid language
  • 401 Unauthorized β€” Invalid token
  • 403 Forbidden β€” Business account not yours
  • 500 Internal Server Error β€” Send failed

Notes:

  • Template must be Approved by Meta to send
  • If template is not approved, send fails with a 500 error
  • Parameters are optional; include only if the template has variables

POST /mark-read

Mark messages as read.

Request:

curl -X POST https://wallin.example/api/whatsapp/mark-read \
  -H "Authorization: Bearer 1|abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "business_account_id": 1,
    "message_id": "wamid_abc123xyz"
  }'

Parameters:

Field Type Required Description
business_account_id integer yes WhatsApp Business Account ID
message_id string yes The WhatsApp message ID (from received message or sent response)

Response (200 OK):

{
  "success": true
}

GET /media/{mediaId}

Download a media file (image, audio, video, document) from a received message.

Request:

curl -X GET https://wallin.example/api/whatsapp/media/abc123xyz \
  -H "Authorization: Bearer 1|abc123..."

Response (200 OK): Binary file content with appropriate Content-Type header (image/jpeg, application/pdf, etc.)

Errors:

  • 404 Not Found β€” Media ID doesn't exist
  • 401 Unauthorized β€” Invalid token
  • 403 Forbidden β€” Media doesn't belong to your organization

GET /media/{mediaId}/url

Get the download URL for a media file (instead of downloading directly).

Request:

curl -X GET https://wallin.example/api/whatsapp/media/abc123xyz/url \
  -H "Authorization: Bearer 1|abc123..."

Response (200 OK):

{
  "url": "https://wallin.example/api/whatsapp/media/abc123xyz",
  "expires_at": "2024-07-20T10:00:00Z"
}

This is useful if you want to embed the download URL in a webpage or email rather than serving the file directly.

Business Account Profile

GET /business-account/{businessAccountId}/profile

Retrieve business profile information.

Request:

curl -X GET https://wallin.example/api/whatsapp/business-account/1/profile \
  -H "Authorization: Bearer 1|abc123..."

Response (200 OK):

{
  "data": {
    "name": "Acme Corp Support",
    "phone_number": "+201012345678",
    "website": "https://example.com",
    "description": "We're here to help",
    "email": "support@example.com",
    "address": "123 Main St, Cairo, Egypt",
    "profile_picture_url": "https://..."
  }
}

PUT /business-account/{businessAccountId}/profile

Update business profile.

Request:

curl -X PUT https://wallin.example/api/whatsapp/business-account/1/profile \
  -H "Authorization: Bearer 1|abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp Support",
    "website": "https://example.com",
    "email": "support@example.com",
    "phone_number": "+201012345678",
    "description": "We're here to help",
    "address": "123 Main St, Cairo, Egypt"
  }'

Response (200 OK):

{
  "success": true
}

Templates

GET /business-account/{businessAccountId}/templates

List all templates for a business account.

Request:

curl -X GET https://wallin.example/api/whatsapp/business-account/1/templates \
  -H "Authorization: Bearer 1|abc123..."

Response (200 OK):

{
  "data": [
    {
      "id": 1,
      "name": "hello_world",
      "status": "APPROVED",
      "language": "en",
      "category": "MARKETING",
      "body": "Hello {{1}}, welcome!"
    }
  ]
}

Media Upload

POST /business-account/{businessAccountId}/upload-media

Upload a media file for use in templates or messages.

Request:

curl -X POST https://wallin.example/api/whatsapp/business-account/1/upload-media \
  -H "Authorization: Bearer 1|abc123..." \
  -F "file=@/path/to/image.jpg" \
  -F "type=image"

Form Parameters:

Field Type Required Description
file file yes Media file (image, document, audio, video)
type string yes One of: image, document, audio, video

Response (200 OK):

{
  "success": true,
  "media_id": "abc123xyz"
}

Use the media_id in template headers or other template components.

Messaging Window

WhatsApp messaging windows limit when you can send:

  • Customer-Service Window β€” You can send freely within 24 hours of the customer's last message
  • Window Closed β€” After 24 hours of silence, you must wait for the customer to message first

Free-form messages fail if the window is closed. Templates tagged MARKETING or OTP may bypass this restriction (depending on Meta's current rules).

Rate Limiting

WhatsApp API calls are rate-limited by Meta and by your plan:

Limit Value
Sends per second per account Determined by Meta WABA quality rating
Monthly message limit Plan-dependent (1K–unlimited)

Exceeding rate limits returns 429 Too Many Requests with a Retry-After header. Queue or retry after the specified delay.

Testing

For local testing, set WHATSAPP_SIMULATE_API=true in .env. Requests will be accepted but no actual message is sent to WhatsApp β€” responses are mocked. Useful for CI/CD and local development.

Was this page helpful?

See Wallin on your own channels.

Book a walkthrough β€” we'll connect a test account and show you the inbox, broadcasts, and automation live.