lang_undefined
lang_undefined
Create a webhook
In your dashboard open Tools → Webhooks → Add webhook. Give it a name, the destination URL on your server, and tick the events it should fire for (SMS, WhatsApp, USSD). A secret is generated for you; copy it from the row's copy button. Every delivery carries that secret so your endpoint can reject anything that did not come from SharkSMS.
The destination must be reachable from the public internet over HTTPS and answer within 5 seconds.
Phone numbers you will receive
You only ever get phone-number identities. A direct message arrives with data[phone] as an international number with a leading + (for example +639760713666); a WhatsApp group message arrives with the full group ID ending in @g.us. Anything else is dropped before it reaches your webhook, auto-replies or flows, so you do not need to defend against odd sender shapes.
Events and payloads
All three events are POSTed as an HTML form body (application/x-www-form-urlencoded) with secret, type, and a nested data array. Not JSON. In PHP that is $_POST["data"]["phone"]; in Express it is req.body["data[phone]"] with the default urlencoded parser, or req.body.data.phone with extended: true.
sms
Fired right after an inbound SMS is saved.
secret=WEBHOOK_SECRET
type=sms
data[id]=2
data[rid]=10593
data[sim]=1
data[device]=00000000-0000-0000-d57d-f30cb6a89289
data[phone]=+639760713666
data[message]=Hello World!
data[timestamp]=1645684231
id is the received message's ID, rid the phone's own message ID, device your device ID, timestamp Unix time of receipt.
Fired right after an inbound WhatsApp message is saved.
secret=WEBHOOK_SECRET
type=whatsapp
data[id]=2
data[wid]=+639760713666
data[phone]=+639760666713
data[message]=Hello World!
data[attachment]=https://sharksms.com/uploads/whatsapp/received/.../file.jpg
data[timestamp]=1645684231
wid is your receiving WhatsApp account's number; phone is the sender (a number, or a @g.us group ID). attachment is a download URL when the message carried media, otherwise false.
ussd
Fired once the carrier answers a USSD request you sent through the API.
secret=WEBHOOK_SECRET
type=ussd
data[id]=98
data[sim]=1
data[device]=00000000-0000-0000-d57d-f30cb6a89289
data[code]=*143#
data[response]=Your balance is 12.40. Valid until 30 Sep.
data[timestamp]=1645684231
What your endpoint must return
HTTP 200. SharkSMS checks the response code of every call: on 200 it logs "Webhook Triggered!"; on anything else, including no answer, it logs "Webhook Failed!" (both visible under Tools → Logger). The call uses a 5-second connect and total timeout and does not retry. A slow endpoint is indistinguishable from a failed one, so acknowledge fast and do the work afterwards.
A minimal receiver in PHP:
<?php
$secret = "WEBHOOK_SECRET"; // from Tools -> Webhooks
if (($_POST["secret"] ?? "") !== $secret) {
http_response_code(403);
exit;
}
$type = $_POST["type"]; // "sms" | "whatsapp" | "ussd"
$data = $_POST["data"]; // array, shape depends on $type
// Acknowledge first, then work. Anything slower than 5s counts as failed.
http_response_code(200);
if (function_exists("fastcgi_finish_request")) fastcgi_finish_request();
if ($type === "sms" && strtoupper(trim($data["message"])) === "C") {
// cancel the appointment for $data["phone"] ...
}
Node.js (Express):
import express from "express";
const app = express();
app.use(express.urlencoded({ extended: true })); // data[phone] -> req.body.data.phone
app.post("/sharksms/webhook", (req, res) => {
if (req.body.secret !== process.env.SHARKSMS_WEBHOOK_SECRET) return res.sendStatus(403);
res.sendStatus(200); // ack first
const { type, data } = req.body;
if (type === "whatsapp") queue.add("inbound", data); // do the work off the request
});
Test it
Every row in Tools → Webhooks has a Simulate button. Pick an event type and it POSTs a realistic fake payload (a sample number, "Hello World!", random IDs) to your URL with your real secret, in exactly the shape above. Use it to confirm the endpoint is reachable and the secret check works before waiting on a real message.
Next: Android gateway setup, or back to the REST API.