Scope Wiser

Scope Wiser API: Sending WhatsApp Messages

The endpoints that send: plain text, interactive reply buttons, images, video, audio and documents, uploading media to reuse, triggering a bot flow, and checking whether a message was delivered.

Last updated Sep 5, 2026

Everything here assumes you have read Scope Wiser API: Overview and Authentication — the base URL, the apiToken parameter and the status response shape.

The rule that governs all of it

Within 24 hours of a customer's last message you may send free-form text, buttons and media. Outside that window WhatsApp delivers only an approved template. This is Meta's rule, not ours, and the API cannot work around it. The WhatsApp 24-Hour Rule and Templates explains it properly.

So: use the endpoints below for people who have messaged you recently, and a template send for everyone else.

Send a text message

GET or POST/whatsapp/send

Parameter

Notes

apiToken

Required

phone_number_id

Required — your WhatsApp number's ID

phone_number

Required — country code first, digits only

message

Required — URL-encode it for GET

curl -X POST \
  'https://connect.scopewiser.com/api/v1/whatsapp/send' \
  -d 'apiToken=API-KEY' \
  -d 'phone_number_id=PHONE-NUMBER-ID' \
  -d 'message=Your order is on its way' \
  -d 'phone_number=PHONE-NUMBER'

A success returns the WhatsApp message id, which you need later to check delivery:

{"status":"1","wa_message_id":"wamid.HBgNODgw...","message":"Message sent successfully."}

Send reply buttons

POST/whatsapp/send/interactive-buttons

Buttons are session messages, so the 24-hour window applies. Send one to three buttons, each title up to 20 characters.

Parameter

Notes

message

Required — the body shown above the buttons

buttons

Required — a JSON array. Each item is a string, or an object with id and title. The id is what comes back when the customer taps

button_header_text

Optional. Ignored if you send a media header

button_footer_text

Optional

media_url or media_id

Optional header media

media_type

image, video or document. Required with media_id, or when media_url has no file extension. Audio is not allowed as a header

media_name

Only used when media_type is document

curl -X POST "https://connect.scopewiser.com/api/v1/whatsapp/send/interactive-buttons" \
  -H "Accept: application/json" \
  -d "apiToken=API-KEY" \
  -d "phone_number_id=PHONE-NUMBER-ID" \
  -d "phone_number=PHONE-NUMBER" \
  -d "message=Would you like to continue?" \
  -d 'buttons=[{"id":"buy_now","title":"Buy Now"},{"id":"details","title":"View Details"}]' \
  -d "button_footer_text=Tap an option"

Give each button a meaningful id. It is what identifies the tap in your webhook, and {"id":"buy_now"} is far easier to handle than matching on the visible title.

Send a file

GET or POST/whatsapp/send/file

One endpoint covers image, video, audio and document. Supply either media_url or media_id.

Parameter

Notes

media_url

A public HTTPS URL. WhatsApp downloads it

media_id

From the upload endpoint below

media_type

image, video, audio or document. Required with media_id, or when the URL has no extension

media_name

Required when media_type is document — the filename the customer sees

media_caption_text

Optional caption for image, video or document. Not for audio

Upload media once, send it many times

POST (multipart/form-data) → /whatsapp/upload/media

Sending the same file by URL repeatedly makes WhatsApp fetch it every time. Upload it once and reuse the id instead.

curl -X POST "https://connect.scopewiser.com/api/v1/whatsapp/upload/media" \
  -H "Authorization: Bearer API-KEY" \
  -H "Accept: application/json" \
  -F "phone_number_id=PHONE-NUMBER-ID" \
  -F "media_file=@/path/to/local/file.jpg"

The file field must be named media_file. The response gives you what the send endpoint wants:

{"status":"1","media_id":"1739230482390482","media_type":"document","media_name":"invoice.pdf",
 "message":"Upload successful..."}

A media_id is tied to the phone_number_id you uploaded against. Upload separately for each number.

The console has a Try upload panel on the page, so you can get a real media_id without writing any code first.

Send a template

Template sends are generated per template rather than through one generic endpoint. On the developer console, under Send Text Message, the Generate API End-point : Send Template Message section lets you pick a WHATSAPP ACCOUNT and a SELECT MESSAGE TEMPLATE, and it builds the call for you with that template's variables in place.

Get the template approved first — Creating & Getting WhatsApp Templates Approved. To list what is available programmatically, call /whatsapp/get/template/list with phone_number_id.

Trigger a bot flow

GET or POST/whatsapp/trigger-bot

Rather than composing a message, you can start a flow you already built.

  1. Call /whatsapp/get/bot-flow-list with phone_number_id to list flows. Each returns a name and a unique_id.

  2. Call /whatsapp/trigger-bot with bot_flow_unique_id and phone_number.

{"status":"1","message":"Bot has been trigger successfully."}

This is usually the better integration. Your system decides when; the flow — already tested, with its buttons, labels and follow-ups — decides what.

Check whether it arrived

GET or POST/whatsapp/get/message-status, with the wa_message_id from the send response.

{"status":"1","message":{"message_status":"delivered","delivery_status_updated_at":"2024-07-28 13:21:03",
 "read_time":null,"failed_time":null,"failed_reason":""}}

A send returning status: "1" means WhatsApp accepted it, not that it reached the handset. If delivery matters, poll this endpoint or read the same information from your webhook.

Read a conversation

GET or POST/whatsapp/get/conversation, with phone_number_id, phone_number, limit (up to 50) and optional offset.

Each message carries sender (bot, or an agent), the raw message_content as JSON, conversation_time, wa_message_id, message_status and failed_reason. Keep paging while nextOffset comes back.

Was this helpful?
Edit this page