13 KiB
MeshCore Event Schemas
This document defines the complete JSON payload schemas for all MeshCore events supported by the API.
Event Categories
Events are categorized by how they're handled:
- Persisted Events: Stored in database tables and available via REST API
- Webhook Events: Trigger HTTP POST notifications when configured
- Informational Events: Logged but not persisted to separate tables
Table of Contents
- Persisted & Webhook Events
- Persisted Events (Non-Webhook)
- Informational Events
- Webhook Payload Format
Persisted & Webhook Events
These events are both stored in the database and trigger webhooks when configured.
ADVERTISEMENT / NEW_ADVERT
Node advertisements announcing presence and metadata.
Database Table: advertisements
Payload Schema:
{
"public_key": "string (64 hex chars)",
"name": "string (optional)",
"adv_type": "string (optional)",
"flags": "integer (optional)",
"lat": "number (optional)",
"lon": "number (optional)"
}
Field Descriptions:
public_key: Node's full 64-character hexadecimal public key (required)name: Node name/alias (e.g., "Gateway-01", "Alice")adv_type: Node type - common values:"chat","repeater","room","companion"(other values may appear from upstream feeds and are normalized by the collector when possible)flags: Node capability/status flags (bitmask)lat: GPS latitude when provided by decoder metadatalon: GPS longitude when provided by decoder metadata
Example:
{
"public_key": "4767c2897c256df8d85a5fa090574284bfd15b92d47359741b0abd5098ed30c4",
"name": "Gateway-01",
"adv_type": "repeater",
"flags": 218,
"lat": 42.470001,
"lon": -71.330001
}
Webhook Trigger: Yes
REST API: GET /api/v1/advertisements
CONTACT_MSG_RECV
Direct/private messages between two nodes.
Database Table: messages
Payload Schema:
{
"pubkey_prefix": "string (12 chars)",
"path_len": "integer (optional)",
"txt_type": "integer (optional)",
"signature": "string (optional)",
"text": "string",
"SNR": "number (optional)",
"sender_timestamp": "integer (optional)"
}
Field Descriptions:
pubkey_prefix: First 12 characters of sender's public key (or source hash prefix in compatibility ingest modes)path_len: Number of hops message traveledtxt_type: Message type indicator (0=plain, 2=signed, etc.)signature: Message signature (8 hex chars) whentxt_type=2text: Message content (required)SNR: Signal-to-Noise Ratio in dBsender_timestamp: Unix timestamp when message was sent
Example:
{
"pubkey_prefix": "01ab2186c4d5",
"path_len": 3,
"txt_type": 0,
"signature": null,
"text": "Hello Bob!",
"SNR": 15.5,
"sender_timestamp": 1732820498
}
Webhook Trigger: Yes
REST API: GET /api/v1/messages
Webhook JSONPath Examples:
- Send only text:
$.data.text - Send text + SNR:
$.data.[text,SNR]
CHANNEL_MSG_RECV
Group/broadcast messages on specific channels.
Database Table: messages
Payload Schema:
{
"channel_idx": "integer (optional)",
"channel_name": "string (optional)",
"pubkey_prefix": "string (12 chars, optional)",
"path_len": "integer (optional)",
"txt_type": "integer (optional)",
"signature": "string (optional)",
"text": "string",
"SNR": "number (optional)",
"sender_timestamp": "integer (optional)"
}
Field Descriptions:
channel_idx: Channel number (0-255) when availablechannel_name: Channel display label (e.g.,"Public","#test") when availablepubkey_prefix: First 12 characters of sender's public key when availablepath_len: Number of hops message traveledtxt_type: Message type indicator (0=plain, 2=signed, etc.)signature: Message signature (8 hex chars) whentxt_type=2text: Message content (required)SNR: Signal-to-Noise Ratio in dBsender_timestamp: Unix timestamp when message was sent
Example:
{
"channel_idx": 4,
"path_len": 10,
"txt_type": 0,
"signature": null,
"text": "Hello from the mesh!",
"SNR": 8.5,
"sender_timestamp": 1732820498
}
Webhook Trigger: Yes
REST API: GET /api/v1/messages
Webhook JSONPath Examples:
- Send only text:
$.data.text - Send channel + text:
$.data.[channel_idx,text]
Compatibility ingest note:
- In LetsMesh upload compatibility mode, packet type
5is normalized toCHANNEL_MSG_RECVand packet types1,2, and7are normalized toCONTACT_MSG_RECVwhen decryptable text is available. - LetsMesh packets without decryptable message text are treated as informational
letsmesh_packetevents instead of message events. - For UI labels, known channel indexes are mapped (
17 -> Public,217 -> #test) and preferred over ambiguous/stale channel-name hints. - Additional channel labels can be provided through
COLLECTOR_LETSMESH_DECODER_KEYSusinglabel=hexentries. - When decoder output includes a human sender (
payload.decoded.decrypted.sender), message text is normalized toName: Message; sender identity remains unknown when only hash/prefix metadata is available.
Compatibility ingest note (advertisements):
- In LetsMesh upload compatibility mode,
statusfeed payloads are persisted as informationalletsmesh_statusevents and are not normalized toADVERTISEMENT. - In LetsMesh upload compatibility mode, decoded payload type
4is normalized toADVERTISEMENTwhen node identity metadata is present. - Payload type
4location metadata (appData.location.latitude/longitude) is mapped to nodelat/lonfor map rendering. - This keeps advertisement persistence aligned with native mode expectations (advertisement traffic only).
Compatibility ingest note (non-message structured events):
- Decoded payload type
9is normalized toTRACE_DATA(traceTag, flags, auth, path hashes, and SNR values). - Decoded payload type
11(Control/NodeDiscoverResp) is normalized tocontactevents for node upsert parity. - Decoded payload type
8is normalized to informationalPATH_UPDATEDevents (hop_count+ path hashes). - Decoded payload type
1can be normalized toTELEMETRY_RESPONSE,BATTERY,PATH_UPDATED, orSTATUS_RESPONSEwhen decrypted response content is structured and parseable.
Persisted Events (Non-Webhook)
These events are stored in the database but do not trigger webhooks.
TRACE_DATA
Network trace path results showing route and signal strength.
Database Table: trace_paths
Payload Schema:
{
"initiator_tag": "integer",
"path_len": "integer (optional)",
"flags": "integer (optional)",
"auth": "integer (optional)",
"path_hashes": "array of strings",
"snr_values": "array of numbers",
"hop_count": "integer (optional)"
}
Field Descriptions:
initiator_tag: Unique trace identifier (0-4294967295)path_len: Length of the pathflags: Trace flags/optionsauth: Authentication/validation datapath_hashes: Array of 2-character node hash identifiers (ordered by hops)snr_values: Array of SNR values corresponding to each hophop_count: Total number of hops
Example:
{
"initiator_tag": 123456789,
"path_len": 3,
"flags": 0,
"auth": 1,
"path_hashes": ["4a", "b3", "fa"],
"snr_values": [25.3, 18.7, 12.4],
"hop_count": 3
}
Webhook Trigger: No
REST API: GET /api/v1/trace-paths
TELEMETRY_RESPONSE
Sensor data from network nodes (temperature, humidity, battery, etc.).
Database Table: telemetry
Payload Schema:
{
"node_public_key": "string (64 hex chars)",
"lpp_data": "bytes (optional)",
"parsed_data": "object (optional)"
}
Field Descriptions:
node_public_key: Full public key of the reporting nodelpp_data: Raw LPP-encoded sensor data (CayenneLPP format)parsed_data: Decoded sensor readings as key-value pairs
Example:
{
"node_public_key": "4767c2897c256df8d85a5fa090574284bfd15b92d47359741b0abd5098ed30c4",
"lpp_data": null,
"parsed_data": {
"temperature": 22.5,
"humidity": 65,
"battery": 3.8,
"pressure": 1013.25
}
}
Webhook Trigger: No
REST API: GET /api/v1/telemetry
CONTACTS
Contact sync event containing all known nodes.
Database Table: Updates nodes table
Payload Schema:
{
"contacts": [
{
"public_key": "string (64 hex chars)",
"name": "string (optional)",
"node_type": "string (optional)"
}
]
}
Field Descriptions:
contacts: Array of contact objectspublic_key: Node's full public keyname: Node name/aliasnode_type: One of:"chat","repeater","room","none"
Example:
{
"contacts": [
{
"public_key": "01ab2186c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1",
"name": "Alice",
"node_type": "chat"
},
{
"public_key": "b3f4e5d6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4",
"name": "Bob",
"node_type": "chat"
}
]
}
Webhook Trigger: No
REST API: GET /api/v1/nodes
Informational Events
These events are logged to events_log table but not persisted to separate tables.
SEND_CONFIRMED
Confirmation that a sent message was delivered.
Payload Schema:
{
"destination_public_key": "string (64 hex chars)",
"round_trip_ms": "integer"
}
Field Descriptions:
destination_public_key: Recipient's full public keyround_trip_ms: Round-trip time in milliseconds
Example:
{
"destination_public_key": "4767c2897c256df8d85a5fa090574284bfd15b92d47359741b0abd5098ed30c4",
"round_trip_ms": 2500
}
STATUS_RESPONSE
Device status information.
Payload Schema:
{
"node_public_key": "string (64 hex chars)",
"status": "string (optional)",
"uptime": "integer (optional)",
"message_count": "integer (optional)"
}
Field Descriptions:
node_public_key: Node's full public keystatus: Status descriptionuptime: Uptime in secondsmessage_count: Total messages processed
Example:
{
"node_public_key": "4767c2897c256df8d85a5fa090574284bfd15b92d47359741b0abd5098ed30c4",
"status": "operational",
"uptime": 86400,
"message_count": 1523
}
BATTERY
Battery status information.
Payload Schema:
{
"battery_voltage": "number",
"battery_percentage": "integer"
}
Field Descriptions:
battery_voltage: Battery voltage (e.g., 3.7V)battery_percentage: Battery level 0-100%
Example:
{
"battery_voltage": 3.8,
"battery_percentage": 75
}
PATH_UPDATED
Notification that routing path to a node has changed.
Payload Schema:
{
"node_public_key": "string (64 hex chars)",
"hop_count": "integer"
}
Field Descriptions:
node_public_key: Target node's full public keyhop_count: Number of hops in new path
Example:
{
"node_public_key": "4767c2897c256df8d85a5fa090574284bfd15b92d47359741b0abd5098ed30c4",
"hop_count": 3
}
Other Informational Events
The following events are logged but have varying or device-specific payloads:
- STATISTICS: Network statistics (varies by implementation)
- DEVICE_INFO: Device hardware/firmware information
- BINARY_RESPONSE: Binary data responses
- CONTROL_DATA: Control/command responses
- RAW_DATA: Raw protocol data
- NEXT_CONTACT: Contact enumeration progress
- ERROR: Error messages with description
- MESSAGES_WAITING: Notification of queued messages
- NO_MORE_MSGS: End of message queue
- RX_LOG_DATA: Receive log data
Webhook Payload Format
All webhook events are wrapped in a standard envelope before being sent:
{
"event_type": "string",
"timestamp": "string (ISO 8601)",
"data": {
// Event-specific payload (see schemas above)
}
}
Example (Channel Message):
{
"event_type": "CHANNEL_MSG_RECV",
"timestamp": "2025-11-28T19:41:38.748379Z",
"data": {
"channel_idx": 4,
"path_len": 10,
"txt_type": 0,
"text": "Hello from the mesh!",
"SNR": 8.5,
"sender_timestamp": 1732820498
}
}
JSONPath Filtering
You can filter webhook payloads using JSONPath expressions:
| JSONPath | Result |
|---|---|
$ |
Full payload (default) |
$.data |
Event data only |
$.data.text |
Message text only |
$.data.[text,SNR] |
Multiple fields as array |
$.event_type |
Event type string |
$.timestamp |
Timestamp string |
See AGENTS.md for webhook configuration details.
Event Flow
- Hardware/Mock MeshCore → Generates raw events
- Event Handler → Processes and persists to database
- Webhook Handler → Sends HTTP POST to configured URLs (if enabled)
- REST API → Query historical data from database
Most events are logged to the events_log table with full payloads for debugging and audit purposes. Some high-frequency informational events (e.g., NEXT_CONTACT) are intentionally excluded from logging to reduce database size.