Mesh Dash Webhook Guide

Using the Webhook API to Send Messages

The MeshDash server provides a simple webhook endpoint at /api/hook that allows you to programmatically send messages to your Meshtastic network. This is useful for integrating external services, alerts, or scripts with your mesh.

To use the webhook, you need to make an HTTP POST request with a JSON payload containing the message details.

POST /api/hook

Sends a text message to a specified Node ID on the Meshtastic network.

How it works:

  • The server receives the JSON payload.
  • It validates that node_id starts with "!" and that message is not empty.
  • If the dashboard is connected to a Meshtastic device, it queues the message for sending using interface.sendText().
  • The sent message is also logged to the dashboard's database as if it were a received packet from the local node (for history tracking).

Endpoint URL:

http://<your-dashboard-ip-or-hostname>:<port>/api/hook

Replace <your-dashboard-ip-or-hostname>:<port> with the actual address where your MeshDash server is running (e.g., http://192.168.1.100:8000/api/hook).

Request Details:

  • Method: POST
  • Required Header: Content-Type: application/json
  • Request Body (JSON - Model: HookMessageRequest):
FieldTypeRequired?Description
node_idstringYesThe destination Node ID. Must start with an exclamation mark (e.g., !aabbccdd).
messagestringYesThe text message content to send. Cannot be empty.
channelintegerNoOptional. The Meshtastic channel index to send the message on (0-7). Defaults to 0 (Primary channel) if not specified.

Example JSON Payload:

{
    "node_id": "!93f84d8f",
    "message": "Alert: Server CPU > 90%!",
    "channel": 0
}

Responses:

  • 202 Accepted: Message queued successfully. The response body will be:{"status": "queued", "detail": "Hook message sent to Meshtastic interface thread for transmission to !nodeid."}
  • 422 Unprocessable Entity: If the request payload is invalid (e.g., missing node_id or message, or node_id format is incorrect). The response body will contain error details.
  • 503 Service Unavailable: If the dashboard is not currently connected to a Meshtastic device.
  • 500 Internal Server Error: If an unexpected error occurs during message processing or sending.

Code Examples

cURL (Linux/macOS/Git Bash/WSL):

curl -X POST "http://YOUR_DASHBOARD_IP:PORT/api/hook" \
-H "Content-Type: application/json" \
-d '{
    "node_id": "!93f84d8f",
    "message": "Automated Alert: System critical!",
    "channel": 1
}'

Python (using requests library):

import requests
import json

dashboard_url = "http://YOUR_DASHBOARD_IP:PORT/api/hook"
payload = {
    "node_id": "!93f84d8f",
    "message": "Hello from Python webhook!",
    "channel": 0  # Optional, defaults to 0
}
headers = {
    "Content-Type": "application/json"
}

try:
    response = requests.post(dashboard_url, headers=headers, data=json.dumps(payload), timeout=10)
    response.raise_for_status()  # Raises an exception for HTTP errors (4xx or 5xx)
    print(f"Success: {response.status_code}")
    print(response.json())
except requests.exceptions.HTTPError as errh:
    print(f"Http Error: {errh}")
    print(f"Response content: {errh.response.text}")
except requests.exceptions.ConnectionError as errc:
    print(f"Error Connecting: {errc}")
except requests.exceptions.Timeout as errt:
    print(f"Timeout Error: {errt}")
except requests.exceptions.RequestException as err:
    print(f"Something Else: {err}")

JavaScript (Node.js using node-fetch or browser fetch):

// For Node.js, you might need to install node-fetch: npm install node-fetch
// const fetch = require('node-fetch'); // Uncomment for Node.js if using CommonJS

async function sendWebhookMessage() {
    const dashboardUrl = "http://YOUR_DASHBOARD_IP:PORT/api/hook";
    const payload = {
        node_id: "!93f84d8f",
        message: "JS Webhook Test 🚀",
        channel: 0
    };

    try {
        const response = await fetch(dashboardUrl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(payload)
        });

        const responseData = await response.json();

        if (response.ok) { // status code 200-299
            console.log("Message sent successfully:", responseData);
        } else {
            console.error(`Error sending message: ${response.status}`, responseData);
        }
    } catch (error) {
        console.error("Network or other error:", error);
    }
}

sendWebhookMessage();

PHP (using cURL extension):

<?php
$dashboardUrl = 'http://YOUR_DASHBOARD_IP:PORT/api/hook';
$payload = [
    'node_id' => '!93f84d8f',
    'message' => 'PHP Webhook Notification!',
    'channel' => 0
];

$jsonData = json_encode($payload);

$ch = curl_init($dashboardUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Content-Length: ' . strlen($jsonData)
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($response === false) {
    echo "cURL Error: " . curl_error($ch);
} else {
    echo "HTTP Status Code: " . $httpCode . "\n";
    echo "Response: " . $response . "\n";
    // $responseData = json_decode($response, true);
    // var_dump($responseData);
}
?>