Facebook Messenger Chatbot Mobile Development
Facebook Messenger Platform is a mature API with a rich set of UI components: Quick Replies, Generic Templates, Buttons, Webview. A bot is registered as a Facebook App and attached to a Facebook Page. For international projects, it's a fully-featured channel.
Setup: App, Page, Webhook
A Messenger bot requires:
- Facebook Developer App (
developers.facebook.com) - Facebook Page (business page)
- HTTPS webhook on your server
- Permissions:
pages_messaging,pages_read_engagement
Webhook verification is a GET request with hub.verify_token and hub.challenge:
from fastapi import FastAPI, Request, Query
app = FastAPI()
VERIFY_TOKEN = "my_secret_verify_token"
PAGE_ACCESS_TOKEN = "EAAxxxxxxx" # From Page settings in Developer Console
@app.get("/webhook")
async def verify(
hub_mode: str = Query(alias="hub.mode"),
hub_verify_token: str = Query(alias="hub.verify_token"),
hub_challenge: str = Query(alias="hub.challenge")
):
if hub_mode == "subscribe" and hub_verify_token == VERIFY_TOKEN:
return int(hub_challenge)
return 403
After verification, subscribe the App to required fields via Graph API: messages, messaging_postbacks, messaging_optins.
Sending Messages: Send API
All messages POST to https://graph.facebook.com/v18.0/me/messages?access_token=PAGE_ACCESS_TOKEN:
import httpx
async def send_message(recipient_id: str, message: dict):
async with httpx.AsyncClient() as client:
await client.post(
f"https://graph.facebook.com/v18.0/me/messages",
params={"access_token": PAGE_ACCESS_TOKEN},
json={"recipient": {"id": recipient_id}, "message": message}
)
# Plain text
await send_message(user_id, {"text": "Hi! How can I help?"})
# Quick Replies — one-time buttons under the message
await send_message(user_id, {
"text": "Choose a category:",
"quick_replies": [
{"content_type": "text", "title": "Shipping", "payload": "DELIVERY"},
{"content_type": "text", "title": "Returns", "payload": "RETURN"},
{"content_type": "location"} # Location sharing button
]
})
Quick Replies disappear after clicking — this is intentional. For a persistent menu, use messenger_profile with Persistent Menu.
Generic Template: Cards with Buttons
Generic Template is a horizontal carousel of cards. Maximum 10 cards, each with: image, title, subtitle, up to 3 buttons:
await send_message(user_id, {
"attachment": {
"type": "template",
"payload": {
"template_type": "generic",
"elements": [
{
"title": "iPhone 15 Pro",
"subtitle": "Titanium. So strong. So light.",
"image_url": "https://cdn.example.com/iphone15.jpg",
"buttons": [
{"type": "web_url", "url": "https://example.com/iphone15",
"title": "Learn more"},
{"type": "postback", "title": "Add to cart",
"payload": "ADD_TO_CART:iphone15"}
]
}
]
}
}
})
postback is a button without a URL that generates a messaging_postbacks event on your webhook with the specified payload. Used for bot commands.
Sender Actions: Typing Indicator
typing_on and typing_off show a typing indicator. Display it before long responses (database queries, LLM calls):
async def send_with_typing(recipient_id: str, message: dict, delay: float = 1.0):
await send_action(recipient_id, "typing_on")
await asyncio.sleep(delay) # Simulate "thinking"
await send_action(recipient_id, "typing_off")
await send_message(recipient_id, message)
Without a typing indicator, responses appear "out of nowhere" — especially critical during LLM latency.
Webview and Extensions
Messenger Extensions lets you open your web app directly in Messenger via a web_url button with messenger_extensions: true. This is similar to Telegram Mini App but with fewer APIs. Use cases: payment forms, catalogs, registrations.
MessengerExtensions.getContext() returns the user's psid for authentication on your server.
Platform Limitations
24+1 window: after the user's last message, the bot can write for 24 hours. After that, only through approved Message Tags (e.g., CONFIRMED_EVENT_UPDATE for event notifications) or the user's subscription to One-Time Notifications.
Development Process
Creating a Facebook App and attaching it to a Page. Webhook setup and subscriptions. Implementing handlers: text messages, postbacks, attachments. UI components: Quick Replies, Generic Template, Persistent Menu. Webview integration for complex forms. Analytics via Facebook Insights.
Timeline Estimates
A basic bot with Quick Replies and Generic Template — 2–3 weeks. A full-featured bot with Webview integration, payment forms, and analytics — 6–10 weeks.







