WhatsApp Sales MCP Sales
Sell on WhatsApp from your own WhatsApp Business number: send approved templates, product cards and payment links, and follow up on customer replies. Runs on the marketplace's own servers and talks directly to Meta's WhatsApp Cloud API, with no third-party messaging provider in between.
Quick start
- Add a WhatsApp Sales connection with the settings below, then click Test configuration.
- Create an API key for your agent.
- Paste the key below, click Test endpoint, and copy the configuration for your platform.
| Endpoint | https://market.oshaani.com/whatsapp-sales (your default connection) or https://market.oshaani.com/whatsapp-sales/<connection-id> |
|---|---|
| Transport | Streamable HTTP (stateless, JSON responses). MCP protocol versions 2024-11-05 to 2025-11-25 and 2026-07-28. |
| Authentication | Authorization: Bearer <API key>, using a key from the API keys page. |
Agent configuration
initialize and tools/list against the endpoint, exactly like an agent. No credits are charged.
Any MCP client that supports remote (Streamable HTTP) servers with custom headers.
{
"name": "whatsapp-sales",
"transport": "streamable-http",
"url": "https://market.oshaani.com/whatsapp-sales",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
~/.cursor/mcp.json (all projects) or .cursor/mcp.json in a project.
{
"mcpServers": {
"whatsapp-sales": {
"url": "https://market.oshaani.com/whatsapp-sales",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
Settings > Developer > Edit Config (claude_desktop_config.json). Uses the mcp-remote bridge; needs Node.js.
{
"mcpServers": {
"whatsapp-sales": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://market.oshaani.com/whatsapp-sales",
"--header",
"Authorization:${AUTH_HEADER}"
],
"env": {
"AUTH_HEADER": "Bearer YOUR_API_KEY"
}
}
}
}
Run in your terminal, or put the JSON in .mcp.json at the project root.
claude mcp add --transport http whatsapp-sales https://market.oshaani.com/whatsapp-sales \
--header "Authorization: Bearer YOUR_API_KEY"
# .mcp.json
{
"mcpServers": {
"whatsapp-sales": {
"type": "http",
"url": "https://market.oshaani.com/whatsapp-sales",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
.vscode/mcp.json (GitHub Copilot agent mode). VS Code prompts for the key once and stores it securely.
{
"inputs": [
{
"type": "promptString",
"id": "oshaani-mcp-key",
"description": "oshaani MCP Marketplace API key",
"password": true
}
],
"servers": {
"whatsapp-sales": {
"type": "http",
"url": "https://market.oshaani.com/whatsapp-sales",
"headers": {
"Authorization": "Bearer ${input:oshaani-mcp-key}"
}
}
}
}
~/.codeium/windsurf/mcp_config.json
{
"mcpServers": {
"whatsapp-sales": {
"serverUrl": "https://market.oshaani.com/whatsapp-sales",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
Responses API remote MCP tool (Python SDK).
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-4.1",
tools=[{
"type": "mcp",
"server_label": "whatsapp_sales",
"server_url": "https://market.oshaani.com/whatsapp-sales",
"headers": {"Authorization": "Bearer YOUR_API_KEY"},
"require_approval": "never", # or "always" to approve each tool call
}],
input="What can you do with these tools?",
)
print(response.output_text)
Messages API MCP connector (Python SDK).
import anthropic
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": "What can you do with these tools?"}],
mcp_servers=[{
"type": "url",
"url": "https://market.oshaani.com/whatsapp-sales",
"name": "whatsapp-sales",
"authorization_token": "YOUR_API_KEY",
}],
betas=["mcp-client-2025-04-04"],
)
print(response.content)
Official MCP Python SDK 2.x (pip install mcp); works inside any agent framework.
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import create_mcp_http_client, streamable_http_client
async def main():
headers = {"Authorization": "Bearer YOUR_API_KEY"}
async with create_mcp_http_client(headers=headers) as http:
async with streamable_http_client("https://market.oshaani.com/whatsapp-sales", http_client=http) as (read, write, *_):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print([tool.name for tool in tools.tools])
asyncio.run(main())
Quick check from a terminal: lists the tools without charging credits.
curl -s https://market.oshaani.com/whatsapp-sales \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-06-18" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Connection settings
Entered once per connection on market.oshaani.com. Secrets are encrypted and never shown again or sent to agents.
| Setting | Type | Description |
|---|---|---|
Phone number IDphone_number_id
required |
string | Meta App Dashboard > WhatsApp > API Setup. This is an ID, not the phone number itself. pattern ^\d{5,25}$ |
Access tokenaccess_token
required secret |
string | Permanent System User token from Meta Business Settings with whatsapp_business_messaging and whatsapp_business_management (and catalog_management for the product tools) |
WhatsApp Business Account IDbusiness_account_id
|
string | Needed to list message templates pattern ^\d{5,25}$ |
Commerce catalog IDcatalog_id
|
string | The catalog connected to this number in Commerce Manager. Enables the product tools. pattern ^\d{5,25}$ |
App secretapp_secret
|
string | Meta App Dashboard > App settings > Basic. Verifies webhook calls; needed to receive customer replies. |
Webhook verify tokenwebhook_verify_token
|
string | Any long random string. Enter the same value as the Verify token in the Meta webhook settings. |
Graph API versionapi_version
|
string default "v24.0" |
pattern ^v\d{2,3}\.0$ |
Tools (13)
list_conversations
read-only
List recent WhatsApp conversations, newest first, with the last message and whether the customer is waiting for a reply
| Argument | Type | Description |
|---|---|---|
awaiting_reply_only |
boolean default false |
Only conversations where the customer sent the last message |
limit |
integer default 20 |
min 1, max 100 |
get_conversation
read-only
Get the message history with one customer, including orders, ad referrals and delivery status
| Argument | Type | Description |
|---|---|---|
phone required |
string | Customer's WhatsApp number in international format with country code, e.g. +919812345678 pattern ^\+?[0-9][0-9 ()-]{5,22}$ |
limit |
integer default 50 |
min 1, max 200 |
mark_as_read
Mark a customer's message (and everything before it) as read, showing blue ticks
| Argument | Type | Description |
|---|---|---|
message_id required |
string | Inbound message ID from get_conversation pattern ^wamid\.[\w=+/-]+$ |
set_marketing_opt_out
Record that a customer opted out of (or back into) marketing messages
| Argument | Type | Description |
|---|---|---|
phone required |
string | Customer's WhatsApp number in international format with country code, e.g. +919812345678 pattern ^\+?[0-9][0-9 ()-]{5,22}$ |
opted_out |
boolean default true |
list_templates
read-only
List message templates with their body text and the parameters each one needs
| Argument | Type | Description |
|---|---|---|
status |
"APPROVED" | "PENDING" | "REJECTED" | "PAUSED" | "ALL" default "APPROVED" |
|
category |
"MARKETING" | "UTILITY" | "AUTHENTICATION" | |
name |
string | Part of the template name |
limit |
integer default 50 |
min 1, max 100 |
send_template
Send an approved template. Works at any time, so use it to start conversations and follow up after 24 hours.
| Argument | Type | Description |
|---|---|---|
to required |
string | Customer's WhatsApp number in international format with country code, e.g. +919812345678 pattern ^\+?[0-9][0-9 ()-]{5,22}$ |
template_name required |
string | pattern ^[a-z0-9_]{1,512}$ |
language |
string default "en_US" |
Template language code from list_templates, e.g. en_US pattern ^[a-z]{2,3}(_[A-Z]{2})?$ |
body_parameters |
array of string | object | Values for the body placeholders: a list in order for {{1}}, {{2}}..., or an object for named placeholders like {{first_name}} |
header_text |
string | Value for a text header placeholder max length 60 |
header_media_url |
string (uri) | Public image, video or PDF URL for a media header min length 1, max length 2083 |
header_media_type |
"image" | "video" | "document" default "image" |
|
button_url_suffix |
string | Value for a dynamic URL button, appended to the URL set in the template max length 2000 |
button_index |
integer default 0 |
Position of that URL button in the template min 0, max 9 |
send_text
Send a text reply. Only delivered within 24 hours of the customer's last message.
| Argument | Type | Description |
|---|---|---|
to required |
string | Customer's WhatsApp number in international format with country code, e.g. +919812345678 pattern ^\+?[0-9][0-9 ()-]{5,22}$ |
text required |
string | min length 1, max length 4096 |
preview_url |
boolean default false |
Show a preview for the first link in the text |
send_buttons
Send a message with up to 3 quick-reply buttons, e.g. 'Book a demo' / 'See prices'. Within 24 hours of the customer's last message.
| Argument | Type | Description |
|---|---|---|
to required |
string | Customer's WhatsApp number in international format with country code, e.g. +919812345678 pattern ^\+?[0-9][0-9 ()-]{5,22}$ |
body required |
string | Message text shown to the customer min length 1, max length 1024 |
buttons required |
array of string | Button labels, max 20 characters each |
header |
string | Optional bold header line max length 60 |
footer |
string | Optional small grey footer line max length 60 |
send_link_button
Send a message with a single link button, e.g. a payment link, booking page or brochure. Within 24 hours of the customer's last message.
| Argument | Type | Description |
|---|---|---|
to required |
string | Customer's WhatsApp number in international format with country code, e.g. +919812345678 pattern ^\+?[0-9][0-9 ()-]{5,22}$ |
body required |
string | Message text shown to the customer min length 1, max length 1024 |
button_text required |
string | e.g. 'Pay now' min length 1, max length 20 |
url required |
string (uri) | min length 1, max length 2083 |
header |
string | Optional bold header line max length 60 |
footer |
string | Optional small grey footer line max length 60 |
send_media
Send an image, video, PDF/document or audio file from a public URL. Within 24 hours of the customer's last message.
| Argument | Type | Description |
|---|---|---|
to required |
string | Customer's WhatsApp number in international format with country code, e.g. +919812345678 pattern ^\+?[0-9][0-9 ()-]{5,22}$ |
media_type required |
"image" | "video" | "document" | "audio" | |
url required |
string (uri) | Publicly reachable file URL; Meta downloads it min length 1, max length 2083 |
caption |
string | Not supported for audio max length 1024 |
filename |
string | Shown for documents, e.g. Price-list.pdf max length 240 |
list_products
read-only
List products in the connected catalog with retailer IDs, prices and availability
| Argument | Type | Description |
|---|---|---|
name_contains |
string | Filter by product name (case-insensitive) max length 100 |
limit |
integer default 25 |
min 1, max 100 |
after |
string | next_cursor from a previous call, for paging |
send_product
Send one product card from the catalog that the customer can view and add to cart. Within 24 hours of the customer's last message.
| Argument | Type | Description |
|---|---|---|
to required |
string | Customer's WhatsApp number in international format with country code, e.g. +919812345678 pattern ^\+?[0-9][0-9 ()-]{5,22}$ |
product_retailer_id required |
string | retailer_id from list_products min length 1, max length 100 |
body |
string | max length 1024 |
footer |
string | Optional small grey footer line max length 60 |
send_product_list
Send a browsable list of up to 30 catalog products grouped into sections. Within 24 hours of the customer's last message.
| Argument | Type | Description |
|---|---|---|
to required |
string | Customer's WhatsApp number in international format with country code, e.g. +919812345678 pattern ^\+?[0-9][0-9 ()-]{5,22}$ |
header required |
string | min length 1, max length 60 |
body required |
string | Message text shown to the customer min length 1, max length 1024 |
sections required |
object | Section title -> product retailer IDs, e.g. {"Bestsellers": ["SKU1", "SKU2"]} |
footer |
string | Optional small grey footer line max length 60 |
Billing & errors
Each successful tool call costs 1 oshaani.com credit. initialize, tools/list, failed calls and timeouts are free.
| JSON-RPC code | Meaning |
|---|---|
-32054 (HTTP 401) | Missing, unknown or revoked API key |
-32053 (HTTP 404) | No WhatsApp Sales connection configured for your organisation, or the connection ID is wrong |
-32055 (HTTP 403) | Connection disabled or origin not allowed |
-32052 (HTTP 429) | Rate limit reached; retry after a minute |
-32050 | Not enough oshaani.com credits for the call |
-32051 | Billing temporarily unavailable; the call was not run |
Errors from WhatsApp Sales itself (bad IDs, permissions) come back as tool results with isError: true so the agent can read and correct them.
See the WhatsApp Sales API documentation.