Services API Reference

Messages Service

class whatsapp_sdk.services.messages.MessagesService(http_client, config, phone_number_id)[source]

Bases: object

Service for sending WhatsApp messages.

Handles all message types: text, media, location, contacts, interactive.

__init__(http_client, config, phone_number_id)[source]

Initialize messages service.

Parameters:
  • http_client (HTTPClient) – HTTP client for API requests

  • config (WhatsAppConfig) – WhatsApp configuration

  • phone_number_id (str) – WhatsApp Business phone number ID

send_text(to, body=None, text=None, preview_url=False)[source]

Send a text message.

Parameters:
  • to (str) – Recipient’s WhatsApp phone number

  • body (str | None) – Text content (convenience parameter)

  • text (str | TextMessage | Dict[str, Any] | None) – Text content or TextMessage object or dict

  • preview_url (bool) – Enable URL preview for links

Returns:

MessageResponse with message ID and status

Return type:

MessageResponse

Examples

# Simple text response = messages.send_text(“+1234567890”, “Hello!”)

# With URL preview response = messages.send_text(

“+1234567890”, “Check out https://example.com”, preview_url=True

)

# Using TextMessage model msg = TextMessage(body=”Hello!”, preview_url=True) response = messages.send_text(“+1234567890”, text=msg)

send_image(to, image, caption=None)[source]

Send an image message.

Parameters:
  • to (str) – Recipient’s WhatsApp phone number

  • image (str | ImageMessage | Dict[str, Any]) – Media ID, URL, ImageMessage object, or dict

  • caption (str | None) – Optional caption for the image

Returns:

MessageResponse with message ID and status

Return type:

MessageResponse

Examples

# Using media ID response = messages.send_image(“+1234567890”, “media_id_123”)

# Using URL with caption response = messages.send_image(

“+1234567890”, “https://example.com/image.jpg”, caption=”Look at this!”

)

# Using ImageMessage model img = ImageMessage(link=”https://example.com/pic.jpg”, caption=”Nice!”) response = messages.send_image(“+1234567890”, img)

send_document(to, document, caption=None, filename=None)[source]

Send a document message.

Parameters:
  • to (str) – Recipient’s WhatsApp phone number

  • document (str | DocumentMessage | Dict[str, Any]) – Media ID, URL, DocumentMessage object, or dict

  • caption (str | None) – Optional caption for the document

  • filename (str | None) – Filename to display (required for URLs)

Returns:

MessageResponse with message ID and status

Return type:

MessageResponse

send_audio(to, audio)[source]

Send an audio message.

Parameters:
  • to (str) – Recipient’s WhatsApp phone number

  • audio (str | AudioMessage | Dict[str, Any]) – Media ID, URL, AudioMessage object, or dict

Returns:

MessageResponse with message ID and status

Return type:

MessageResponse

send_video(to, video, caption=None)[source]

Send a video message.

Parameters:
  • to (str) – Recipient’s WhatsApp phone number

  • video (str | VideoMessage | Dict[str, Any]) – Media ID, URL, VideoMessage object, or dict

  • caption (str | None) – Optional caption for the video

Returns:

MessageResponse with message ID and status

Return type:

MessageResponse

send_sticker(to, sticker)[source]

Send a sticker message.

Parameters:
Returns:

MessageResponse with message ID and status

Return type:

MessageResponse

send_location(to, latitude, longitude, name=None, address=None)[source]

Send a location message.

Parameters:
  • to (str) – Recipient’s WhatsApp phone number

  • latitude (float) – Latitude coordinate

  • longitude (float) – Longitude coordinate

  • name (str | None) – Optional location name

  • address (str | None) – Optional location address

Returns:

MessageResponse with message ID and status

Return type:

MessageResponse

Examples

# Basic location response = messages.send_location(

“+1234567890”, 37.4847, -122.1477

)

# With name and address response = messages.send_location(

“+1234567890”, 37.4847, -122.1477, name=”Meta Headquarters”, address=”1 Hacker Way, Menlo Park, CA”

)

send_contact(to, contacts)[source]

Send contact information.

Parameters:
  • to (str) – Recipient’s WhatsApp phone number

  • contacts (List[Contact] | ContactMessage | Dict[str, Any]) – List of Contact objects, ContactMessage, or dict

Returns:

MessageResponse with message ID and status

Return type:

MessageResponse

Examples

# Using Contact model from whatsapp_sdk.models import Contact, Name, Phone

contact = Contact(
name=Name(

formatted_name=”John Doe”, first_name=”John”, last_name=”Doe”

), phones=[Phone(phone=”+1234567890”, type=”MOBILE”)]

) response = messages.send_contact(“+1234567890”, [contact])

send_interactive(to, interactive)[source]

Send an interactive message with buttons or lists.

Parameters:
Returns:

MessageResponse with message ID and status

Return type:

MessageResponse

Examples

# Button message from whatsapp_sdk.models import (

InteractiveMessage, InteractiveBody, InteractiveAction, Button

)

interactive = InteractiveMessage(

type=”button”, body=InteractiveBody(text=”Choose an option:”), action=InteractiveAction(

buttons=[

Button(type=”reply”, reply={“id”: “1”, “title”: “Yes”}), Button(type=”reply”, reply={“id”: “2”, “title”: “No”})

]

)

) response = messages.send_interactive(“+1234567890”, interactive)

mark_as_read(message_id, typing_indicator=False)[source]

Mark a message as read and optionally show typing indicator.

Parameters:
  • message_id (str) – WhatsApp message ID to mark as read

  • typing_indicator (bool) – If True, shows typing indicator for up to 25 seconds

Returns:

MessageResponse confirming the action

Return type:

MessageResponse

Examples

# Mark as read only response = messages.mark_as_read(“wamid.xxx”)

# Mark as read and show typing indicator response = messages.mark_as_read(“wamid.xxx”, typing_indicator=True)

send_typing_indicator(message_id)[source]

Send typing indicator without marking message as read.

Shows the typing indicator for up to 25 seconds or until a message is sent. Note: This also marks the message as read.

Parameters:

message_id (str) – WhatsApp message ID to respond to

Returns:

MessageResponse confirming the action

Return type:

MessageResponse

Example

# Show typing indicator while processing messages.send_typing_indicator(“wamid.xxx”) # Process message… messages.send_text(to, “Response ready!”)

Templates Service

class whatsapp_sdk.services.templates.TemplatesService(http_client, config, phone_number_id)[source]

Bases: object

Service for managing WhatsApp message templates.

Handles template operations: send, create, list, get, delete, update.

__init__(http_client, config, phone_number_id)[source]

Initialize templates service.

Parameters:
  • http_client (HTTPClient) – HTTP client for API requests

  • config (WhatsAppConfig) – WhatsApp configuration

  • phone_number_id (str) – WhatsApp Business phone number ID

send(to, template_name, language_code='en_US', components=None)[source]

Send a template message.

Parameters:
  • to (str) – Recipient’s WhatsApp phone number

  • template_name (str) – Name of the approved template

  • language_code (str) – Language code (e.g., en_US, es_ES)

  • components (List[TemplateComponent] | List[Dict[str, Any]] | None) – Template components with parameters

Returns:

MessageResponse with message ID and status

Return type:

MessageResponse

Examples

# Simple template without parameters response = templates.send(

to=”+1234567890”, template_name=”hello_world”, language_code=”en_US”

)

# Template with parameters from whatsapp_sdk.models import TemplateComponent, TemplateParameter

components = [
TemplateComponent(

type=”body”, parameters=[

TemplateParameter(type=”text”, text=”John”), TemplateParameter(type=”text”, text=”ABC123”)

]

)

]

response = templates.send(

to=”+1234567890”, template_name=”order_confirmation”, language_code=”en_US”, components=components

)

# Template with header image components = [

TemplateComponent(

type=”header”, parameters=[

TemplateParameter(

type=”image”, image={“link”: “https://example.com/image.jpg”}

)

]

), TemplateComponent(

type=”body”, parameters=[

TemplateParameter(type=”text”, text=”John”)

]

)

]

create(name, category, language, components, allow_category_change=True)[source]

Create a new message template.

Parameters:
  • name (str) – Template name (must be unique)

  • category (str) – Template category (MARKETING, UTILITY, or AUTHENTICATION)

  • language (str) – Language code (e.g., en_US)

  • components (List[Dict[str, Any]]) – Template components (header, body, footer, buttons)

  • allow_category_change (bool) – Allow automatic category change if needed

Returns:

TemplateResponse with template ID and status

Return type:

TemplateResponse

Examples

# Create a simple template response = templates.create(

name=”welcome_message”, category=”MARKETING”, language=”en_US”, components=[

{

“type”: “HEADER”, “format”: “TEXT”, “text”: “Welcome to {{1}}!”

}, {

“type”: “BODY”, “text”: “Hi {{1}}, thanks for joining {{2}}. We’re excited to have you!”

}, {

“type”: “FOOTER”, “text”: “Reply STOP to unsubscribe”

}

]

)

# Create template with buttons response = templates.create(

name=”appointment_reminder”, category=”UTILITY”, language=”en_US”, components=[

{

“type”: “BODY”, “text”: “Your appointment is on {{1}} at {{2}}”

}, {

“type”: “BUTTONS”, “buttons”: [

{

“type”: “QUICK_REPLY”, “text”: “Confirm”

}, {

“type”: “QUICK_REPLY”, “text”: “Reschedule”

}

]

}

]

)

list(limit=None, after=None, fields=None)[source]

List all message templates.

Parameters:
  • limit (int | None) – Maximum number of templates to return

  • after (str | None) – Cursor for pagination

  • fields (List[str] | None) – Specific fields to include in response

Returns:

TemplateListResponse with list of templates

Return type:

TemplateListResponse

Example

# List all templates templates_list = templates.list()

# List with pagination templates_list = templates.list(limit=10)

# Get next page next_page = templates.list(after=templates_list.paging[“cursors”][“after”])

get(template_id)[source]

Get details of a specific template.

Parameters:

template_id (str) – Template ID

Returns:

Template with full details

Return type:

Template

Example

template = templates.get(“12345678”)

delete(template_name)[source]

Delete a message template.

Parameters:

template_name (str) – Name of the template to delete

Returns:

True if deletion was successful

Return type:

bool

Example

success = templates.delete(“old_template”)

update(template_id, components)[source]

Update template components.

Note: Only certain template elements can be updated after creation.

Parameters:
  • template_id (str) – Template ID to update

  • components (List[Dict[str, Any]]) – Updated components

Returns:

TemplateResponse with update status

Return type:

TemplateResponse

Example

response = templates.update(

template_id=”12345678”, components=[

{

“type”: “BODY”, “text”: “Updated message text with {{1}} parameter”

}

]

)

Media Service

class whatsapp_sdk.services.media.MediaService(http_client, config, phone_number_id)[source]

Bases: object

Service for managing WhatsApp media.

Handles media operations: upload, download, get URL, delete.

__init__(http_client, config, phone_number_id)[source]

Initialize media service.

Parameters:
  • http_client (HTTPClient) – HTTP client for API requests

  • config (WhatsAppConfig) – WhatsApp configuration

  • phone_number_id (str) – WhatsApp Business phone number ID

upload(file_path, mime_type=None)[source]

Upload a media file from local path.

Parameters:
  • file_path (str) – Path to the file to upload

  • mime_type (str | None) – MIME type of the file (auto-detected if not provided)

Returns:

MediaUploadResponse with media ID

Raises:

WhatsAppMediaError – If file doesn’t exist or upload fails

Return type:

MediaUploadResponse

Examples

# Upload an image response = media.upload(“/path/to/image.jpg”) media_id = response.id

# Upload with explicit MIME type response = media.upload(

“/path/to/document.pdf”, mime_type=”application/pdf”

)

upload_from_bytes(file_bytes, mime_type, filename)[source]

Upload media from bytes in memory.

Parameters:
  • file_bytes (bytes) – File content as bytes

  • mime_type (str) – MIME type of the file

  • filename (str) – Filename to use for the upload

Returns:

MediaUploadResponse with media ID

Return type:

MediaUploadResponse

Examples

# Upload from bytes with open(“image.jpg”, “rb”) as f:

file_bytes = f.read()

response = media.upload_from_bytes(

file_bytes=file_bytes, mime_type=”image/jpeg”, filename=”photo.jpg”

)

# Upload generated content import io from PIL import Image

img = Image.new(‘RGB’, (100, 100), color=’red’) img_bytes = io.BytesIO() img.save(img_bytes, format=’JPEG’)

response = media.upload_from_bytes(

file_bytes=img_bytes.getvalue(), mime_type=”image/jpeg”, filename=”generated.jpg”

)

get_url(media_id)[source]

Get download URL for a media file.

Parameters:

media_id (str) – WhatsApp media ID

Returns:

Download URL (expires after 5 minutes)

Return type:

str

Examples

# Get URL for downloading url = media.get_url(“media_id_123”)

# Use the URL to download import requests response = requests.get(url, headers={

“Authorization”: f”Bearer {access_token}”

}) content = response.content

download(media_id)[source]

Download media file content.

Parameters:

media_id (str) – WhatsApp media ID

Returns:

File content as bytes

Return type:

bytes

Examples

# Download media content = media.download(“media_id_123”)

# Save to file with open(“downloaded_file.jpg”, “wb”) as f:

f.write(content)

download_to_file(media_id, file_path)[source]

Download media directly to a file.

Parameters:
  • media_id (str) – WhatsApp media ID

  • file_path (str) – Path where to save the file

Returns:

Path to the saved file

Return type:

str

Examples

# Download to specific path saved_path = media.download_to_file(

“media_id_123”, “/path/to/save/image.jpg”

)

delete(media_id)[source]

Delete a media file.

Parameters:

media_id (str) – WhatsApp media ID to delete

Returns:

True if deletion was successful

Return type:

bool

Examples

# Delete media success = media.delete(“media_id_123”) if success:

print(“Media deleted successfully”)

Webhooks Service

class whatsapp_sdk.services.webhooks.WebhooksService(config)[source]

Bases: object

Service for handling WhatsApp webhooks.

Handles webhook verification, signature validation, and event parsing.

__init__(config)[source]

Initialize webhooks service.

Parameters:

config (WhatsAppConfig) – WhatsApp configuration

verify_token(token)[source]

Verify webhook token during setup.

Parameters:

token (str) – Token received from webhook verification request

Returns:

True if token is valid

Return type:

bool

Example

# In your webhook endpoint if webhooks.verify_token(request.args.get(“hub.verify_token”)):

return request.args.get(“hub.challenge”)

verify_signature(signature, payload)[source]

Verify webhook signature for security.

Parameters:
  • signature (str) – X-Hub-Signature-256 header value

  • payload (bytes) – Raw request body as bytes

Returns:

True if signature is valid

Return type:

bool

Example

# In your webhook endpoint signature = request.headers.get(“X-Hub-Signature-256”) payload = request.get_data()

if not webhooks.verify_signature(signature, payload):

return “Invalid signature”, 403

parse_event(payload)[source]

Parse webhook event payload.

Parameters:

payload (Dict[str, Any]) – Webhook JSON payload

Returns:

WebhookEvent object with parsed data

Return type:

WebhookEvent

Example

# In your webhook endpoint event = webhooks.parse_event(request.json)

for entry in event.entry:
for change in entry.changes:
if change.value.messages:
for message in change.value.messages:

process_message(message)

process_message(message)[source]

Process a single message from webhook.

Parameters:

message (Dict[str, Any]) – Message dictionary from webhook

Returns:

WebhookMessage object

Return type:

WebhookMessage

Example

# Process incoming message webhook_message = webhooks.process_message(message_dict)

if webhook_message.type == “text”:

print(f”Received text: {webhook_message.text.body}”)

elif webhook_message.type == “image”:

print(f”Received image: {webhook_message.image.id}”)

process_status(status)[source]

Process a status update from webhook.

Parameters:

status (Dict[str, Any]) – Status dictionary from webhook

Returns:

WebhookStatus object

Return type:

WebhookStatus

Example

# Process status update webhook_status = webhooks.process_status(status_dict)

if webhook_status.status == “delivered”:

print(f”Message {webhook_status.id} was delivered”)

elif webhook_status.status == “read”:

print(f”Message {webhook_status.id} was read”)

handle_verification(mode, token, challenge)[source]

Handle webhook verification request.

Parameters:
  • mode (str) – hub.mode parameter (should be “subscribe”)

  • token (str) – hub.verify_token parameter

  • challenge (str) – hub.challenge parameter to echo back

Returns:

Challenge string if verification successful, None otherwise

Return type:

str | None

Example

# FastAPI example @app.get(“/webhook”) def verify_webhook(

hub_mode: str = Query(None, alias=”hub.mode”), hub_verify_token: str = Query(None, alias=”hub.verify_token”), hub_challenge: str = Query(None, alias=”hub.challenge”)

):
result = webhooks.handle_verification(

hub_mode, hub_verify_token, hub_challenge

) if result:

return result

return Response(status_code=403)

handle_event(signature, payload)[source]

Handle incoming webhook event with validation.

Parameters:
  • signature (str) – X-Hub-Signature-256 header value

  • payload (bytes) – Raw request body as bytes

Returns:

Parsed WebhookEvent if valid

Raises:

WhatsAppWebhookError – If signature is invalid

Return type:

WebhookEvent

Example

# FastAPI example @app.post(“/webhook”) async def handle_webhook(

request: Request, x_hub_signature_256: str = Header(None)

):

body = await request.body()

try:

event = webhooks.handle_event(x_hub_signature_256, body) # Process event… return {“status”: “ok”}

except WhatsAppWebhookError as e:

return Response(status_code=403)

extract_messages(event)[source]

Extract all messages from a webhook event.

Parameters:

event (WebhookEvent) – WebhookEvent object

Returns:

List of WebhookMessage objects

Return type:

List[WebhookMessage]

Example

event = webhooks.parse_event(payload) messages = webhooks.extract_messages(event)

for message in messages:

print(f”From: {message.from_}”) print(f”Type: {message.type}”)

extract_statuses(event)[source]

Extract all status updates from a webhook event.

Parameters:

event (WebhookEvent) – WebhookEvent object

Returns:

List of WebhookStatus objects

Return type:

List[WebhookStatus]

Example

event = webhooks.parse_event(payload) statuses = webhooks.extract_statuses(event)

for status in statuses:

print(f”Message ID: {status.id}”) print(f”Status: {status.status}”)

HTTP Client

The underlying HTTP client provides additional methods for media operations:

class whatsapp_sdk.http_client.HTTPClient(config)[source]

Bases: object

Synchronous HTTP client for WhatsApp API requests.

Handles: - Request/response processing - Error handling and retries - Rate limiting - Authentication

__init__(config)[source]

Initialize HTTP client.

Parameters:

config (WhatsAppConfig) – WhatsApp configuration

post(endpoint, json=None, **kwargs)[source]

Make POST request to WhatsApp API.

Parameters:
  • endpoint (str) – API endpoint (can be relative or absolute)

  • json (Dict[str, Any] | None) – JSON payload

  • **kwargs (Any) – Additional httpx request parameters

Returns:

Response data as dictionary

Raises:
Return type:

Dict[str, Any]

get(endpoint, params=None, **kwargs)[source]

Make GET request to WhatsApp API.

Parameters:
  • endpoint (str) – API endpoint

  • params (Dict[str, Any] | None) – Query parameters

  • **kwargs (Any) – Additional httpx request parameters

Returns:

Response data as dictionary

Return type:

Dict[str, Any]

delete(endpoint, **kwargs)[source]

Make DELETE request to WhatsApp API.

Parameters:
  • endpoint (str) – API endpoint

  • **kwargs (Any) – Additional httpx request parameters

Returns:

Response data as dictionary

Return type:

Dict[str, Any]

upload_multipart(endpoint, files, data=None, **kwargs)[source]

Make POST request with multipart/form-data for file uploads.

Parameters:
  • endpoint (str) – API endpoint

  • files (Dict[str, Any]) – Files to upload in httpx format

  • data (Dict[str, Any] | None) – Form data to include

  • **kwargs (Any) – Additional httpx request parameters

Returns:

Response data as dictionary

Raises:
Return type:

Dict[str, Any]

download_binary(url, **kwargs)[source]

Download binary content from a URL.

Parameters:
  • url (str) – Full URL to download from

  • **kwargs (Any) – Additional httpx request parameters

Returns:

Binary content as bytes

Raises:

WhatsAppAPIError – For API errors

Return type:

bytes

close()[source]

Close the HTTP client.

__enter__()[source]

Context manager entry.

__exit__(exc_type, exc_val, exc_tb)[source]

Context manager exit.

HTTPClient.upload_multipart(endpoint, files, data=None, **kwargs)[source]

Make POST request with multipart/form-data for file uploads.

Parameters:
  • endpoint (str) – API endpoint

  • files (Dict[str, Any]) – Files to upload in httpx format

  • data (Dict[str, Any] | None) – Form data to include

  • **kwargs (Any) – Additional httpx request parameters

Returns:

Response data as dictionary

Raises:
Return type:

Dict[str, Any]

Make POST request with multipart/form-data for file uploads.

Used internally by MediaService for uploading files with proper multipart encoding support.

HTTPClient.download_binary(url, **kwargs)[source]

Download binary content from a URL.

Parameters:
  • url (str) – Full URL to download from

  • **kwargs (Any) – Additional httpx request parameters

Returns:

Binary content as bytes

Raises:

WhatsAppAPIError – For API errors

Return type:

bytes

Download binary content from a URL.

Used internally by MediaService for downloading media files as binary content with proper error handling and retry logic.