12 KiB
API Documentation
Base URL: http(s)://<host>
All endpoints return JSON. Timestamps are either ISO 8601 strings or *_us values in
microseconds since epoch.
1. Nodes API
GET /api/nodes
Returns a list of nodes, with optional filtering.
Query Parameters
node_id(optional, int): Exact node ID.role(optional, string): Node role.channel(optional, string): Channel name.hw_model(optional, string): Hardware model.days_active(optional, int): Nodes seen within the last N days.
Response Example
{
"nodes": [
{
"id": 42,
"node_id": 1234,
"long_name": "Alice",
"short_name": "A",
"hw_model": "T-Beam",
"firmware": "1.2.3",
"role": "client",
"last_lat": 377749000,
"last_long": -1224194000,
"channel": "main",
"last_seen_us": 1736370123456789
}
]
}
2. Packets API
GET /api/packets
Returns packets with optional filters.
Query Parameters
packet_id(optional, int): Return exactly one packet (overrides other filters).limit(optional, int): Max packets to return, clamped 1-1000. Default:50.since(optional, int): Only packets imported after this microsecond timestamp.portnum(optional, int): Filter by port number.contains(optional, string): Payload substring filter.from_node_id(optional, int): Filter by sender node ID.to_node_id(optional, int): Filter by recipient node ID.node_id(optional, int): Legacy filter matching either from or to node ID.
Response Example
{
"packets": [
{
"id": 123,
"import_time_us": 1736370123456789,
"channel": "main",
"from_node_id": 5678,
"to_node_id": 91011,
"portnum": 1,
"long_name": "Alice",
"payload": "Hello, Bob!",
"to_long_name": "Bob",
"reply_id": 122
}
],
"latest_import_time": 1736370123456789
}
Notes
- For
portnum=1(text messages), packets are filtered to remove sequence-only payloads. latest_import_timeis returned when available for incremental polling (microseconds).
3. Channels API
GET /api/channels
Returns channels seen in a time period.
Query Parameters
period_type(optional, string):hourorday. Default:hour.length(optional, int): Number of periods to look back. Default:24.
Response Example
{
"channels": ["LongFast", "MediumFast", "ShortFast"]
}
4. Stats API
GET /api/stats
Returns packet statistics aggregated by time periods, with optional filtering.
Query Parameters
period_type(optional, string):hourorday. Default:hour.length(optional, int): Number of periods to include. Default:24.channel(optional, string): Filter by channel (case-insensitive).portnum(optional, int): Filter by port number.to_node(optional, int): Filter by destination node ID.from_node(optional, int): Filter by source node ID.node(optional, int): If provided, return combinedsentandseentotals for that node.
Response Example (series)
{
"period_type": "hour",
"length": 24,
"channel": "LongFast",
"portnum": 1,
"to_node": 12345678,
"from_node": 87654321,
"data": [
{ "period": "2025-08-08 14:00", "count": 10 },
{ "period": "2025-08-08 15:00", "count": 7 }
]
}
Response Example (node totals)
{
"node_id": 12345678,
"period_type": "hour",
"length": 24,
"sent": 42,
"seen": 58
}
GET /api/stats/count
Returns total packet counts, optionally filtered.
Query Parameters
packet_id(optional, int): Filter packet_seen by packet ID.period_type(optional, string):hourorday.length(optional, int): Number of periods to include.channel(optional, string): Filter by channel.from_node(optional, int): Filter by source node ID.to_node(optional, int): Filter by destination node ID.
Response Example
{
"total_packets": 12345,
"total_seen": 67890
}
GET /api/stats/top
Returns nodes sorted by packets seen, with pagination.
Query Parameters
period_type(optional, string):hourorday. Default:day.length(optional, int): Number of periods to include. Default:1.channel(optional, string): Filter by channel.limit(optional, int): Max nodes to return. Default:20, max100.offset(optional, int): Pagination offset. Default:0.
Response Example
{
"total": 250,
"limit": 20,
"offset": 0,
"nodes": [
{
"node_id": 1234,
"long_name": "Alice",
"short_name": "A",
"channel": "main",
"sent": 100,
"seen": 240,
"avg": 2.4
}
]
}
5. Edges API
GET /api/edges
Returns network edges (connections between nodes) based on traceroutes and neighbor info. Traceroute edges are collected over the last 12 hours. Neighbor edges are based on port 71 packets.
A completed traceroute is observed as a response packet, whose from/to are reversed
with respect to the traced path, so edges are built as to -> route[] -> from. route[]
may contain 0xFFFFFFFF placeholders for hops the mesh could not identify; the edges on
either side of such a placeholder are omitted, because the nodes around an unknown hop
are not neighbours.
Query Parameters
type(optional, string):tracerouteorneighbor. If omitted, returns both.node_id(optional, int): Filter edges to only those touching a node.
Response Example
{
"edges": [
{ "from": 12345678, "to": 87654321, "type": "traceroute" },
{ "from": 11111111, "to": 22222222, "type": "neighbor" }
]
}
6. Config API
GET /api/snapshots/daily
Returns stored daily snapshots. For new snapshots, packet_count is the number of
packet records imported during date (00:00 UTC inclusive to the next midnight
exclusive). The scheduled capture records the previous complete UTC day. Repeated
observations of the same packet are not counted separately. node_count counts distinct
packet senders whose packets were imported or observed during that UTC day (including
observations of previously imported packets). gateway_count counts distinct MQTT
gateways with packet observations imported during that day. These are activity counts,
not database totals; recipients alone do not count as active nodes. Activity uses local
import timestamps, not device timestamps. Older snapshots retain their originally stored
counts and are not automatically converted. Counts depend on the packet and observation
history still retained at capture time.
GET /api/config
Returns a safe subset of server configuration.
site.map_channel_colors contains channel color overrides from the optional
[map_channel_colors] INI section. Each entry is channel = #RRGGBB; invalid colors
are omitted. Channel matching on the map ignores case, spaces, hyphens, and underscores.
Unlisted channels use generated colors. For example:
[map_channel_colors]
LongFast = #4363d8
LocalChat = #18aa18
Restart the web server and reload the map after changing these settings. Omitting the section uses generated colors for every channel.
Response Example
{
"site": {
"domain": "example.com",
"language": "en",
"title": "Meshview",
"message": "",
"starting": "/chat",
"nodes": "true",
"chat": "true",
"everything": "true",
"graphs": "true",
"stats": "true",
"net": "true",
"map": "true",
"top": "true",
"map_top_left_lat": 39.0,
"map_top_left_lon": -123.0,
"map_bottom_right_lat": 36.0,
"map_bottom_right_lon": -121.0,
"map_interval": 3,
"firehose_interval": 3,
"weekly_net_message": "Weekly Mesh check-in message.",
"net_tag": "#BayMeshNet",
"version": "3.0.0"
},
"mqtt": {
"server": "mqtt.example.com",
"topics": ["msh/region/#"]
},
"cleanup": {
"enabled": "false",
"days_to_keep": "14",
"hour": "2",
"minute": "0",
"vacuum": "false"
}
}
7. Language API
GET /api/lang
Returns translation strings.
Query Parameters
lang(optional, string): Language code (e.g.,en,es). Default from config oren.section(optional, string): Return only one section (e.g.,nodelist,firehose).
Response Example
{
"title": "Meshview",
"search_placeholder": "Search..."
}
8. Packets Seen API
GET /api/packets_seen/{packet_id}
Returns packet_seen entries for a packet.
Path Parameters
packet_id(required, int): Packet ID.
Response Example
{
"seen": [
{
"packet_id": 123,
"node_id": 456,
"rx_time": "2025-07-22T12:45:00",
"hop_limit": 7,
"hop_start": 0,
"channel": "main",
"rx_snr": 5.0,
"rx_rssi": -90,
"topic": "msh/region/#",
"import_time_us": 1736370123456789
}
]
}
9. Traceroute API
GET /api/traceroute/{packet_id}
Returns traceroute details and derived paths for a packet.
Path Parameters
packet_id(required, int): Packet ID.
A completed traceroute is observed as a response packet, whose from/to are reversed
with respect to the traced path. initiator and target resolve this: the forward path
runs initiator -> forward_hops -> target and the return path runs
target -> reverse_hops -> initiator, in both directions of travel. forward_hops and
reverse_hops contain only the intermediate hops, never the endpoints.
A gateway usually reports a response that is still travelling home, so reverse_hops is
often incomplete. reverse_complete says whether that observation had reached the
initiator; only then does the corresponding winning_paths.reverse entry end at the
initiator.
winning_paths is built from response observations, since a response proves the request
reached the target. complete on a unique_forward_paths entry says whether some
response reported that hop list, and so whether it is known to end at the target.
Response Example
{
"packet": {
"id": 123,
"from": 222,
"to": 111,
"initiator": 111,
"target": 222,
"channel": "main"
},
"traceroute_packets": [
{
"index": 0,
"gateway_node_id": 333,
"done": true,
"forward_hops": [444, 555],
"reverse_hops": [555, 444],
"reverse_complete": true
}
],
"unique_forward_paths": [
{ "path": [444, 555], "count": 2, "complete": true }
],
"unique_reverse_paths": [
[555, 444]
],
"winning_paths": {
"forward": [[111, 444, 555, 222]],
"reverse": [[222, 555, 444, 111]]
}
}
10. Health API
GET /health
Returns service health and database status.
Response Example
{
"status": "healthy",
"timestamp": "2025-07-22T12:45:00+00:00",
"version": "3.0.3",
"git_revision": "abc1234",
"cleanup": {
"enabled": true,
"days_to_keep": 14,
"scheduled_time": "02:00",
"vacuum": false,
"status": "ok",
"status_file": "dbcleanup.status.json",
"last_run": {
"status": "ok",
"started_at": "2026-06-04T09:00:00+00:00",
"completed_at": "2026-06-04T09:00:03+00:00",
"cutoff_at": "2026-05-21T09:00:00+00:00",
"days_to_keep": 14,
"vacuum_requested": false,
"vacuum_completed": false,
"rows_deleted": {
"packet": 1200,
"packet_seen": 3400,
"traceroute": 42,
"node": 3
},
"error": null
}
},
"backup": {
"enabled": true,
"backup_dir": "./backups",
"scheduled_time": "02:00",
"status": "ok",
"status_file": "dbbackup.status.json",
"last_run": {
"status": "ok",
"started_at": "2026-06-04T09:00:00+00:00",
"completed_at": "2026-06-04T09:00:02+00:00",
"backup_dir": "./backups",
"database_path": "packets.db",
"backup_file": "backups/packets_backup_20260604_090000.db.gz",
"original_size_bytes": 12939444,
"compressed_size_bytes": 4211560,
"compression_percent": 67.5,
"error": null
}
},
"database": "connected",
"database_size": "12.34 MB",
"database_size_bytes": 12939444
}
11. Version API
GET /version
Returns version metadata.
Response Example
{
"version": "3.0.3",
"release_date": "2026-1-15",
"git_revision": "abc1234",
"git_revision_short": "abc1234"
}