Files
meshcore-hub/SCHEMAS.md

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

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 metadata
  • lon: 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 traveled
  • txt_type: Message type indicator (0=plain, 2=signed, etc.)
  • signature: Message signature (8 hex chars) when txt_type=2
  • text: Message content (required)
  • SNR: Signal-to-Noise Ratio in dB
  • sender_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 available
  • channel_name: Channel display label (e.g., "Public", "#test") when available
  • pubkey_prefix: First 12 characters of sender's public key when available
  • path_len: Number of hops message traveled
  • txt_type: Message type indicator (0=plain, 2=signed, etc.)
  • signature: Message signature (8 hex chars) when txt_type=2
  • text: Message content (required)
  • SNR: Signal-to-Noise Ratio in dB
  • sender_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 5 is normalized to CHANNEL_MSG_RECV and packet types 1, 2, and 7 are normalized to CONTACT_MSG_RECV when decryptable text is available.
  • LetsMesh packets without decryptable message text are treated as informational letsmesh_packet events 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_KEYS using label=hex entries.
  • When decoder output includes a human sender (payload.decoded.decrypted.sender), message text is normalized to Name: Message; sender identity remains unknown when only hash/prefix metadata is available.

Compatibility ingest note (advertisements):

  • In LetsMesh upload compatibility mode, decoded payload types 4 and 11 are normalized to ADVERTISEMENT when node identity metadata is present.
  • Payload type 4 location metadata (appData.location.latitude/longitude) is mapped to node lat/lon for map rendering.

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 path
  • flags: Trace flags/options
  • auth: Authentication/validation data
  • path_hashes: Array of 2-character node hash identifiers (ordered by hops)
  • snr_values: Array of SNR values corresponding to each hop
  • hop_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 node
  • lpp_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 objects
  • public_key: Node's full public key
  • name: Node name/alias
  • node_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 key
  • round_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 key
  • status: Status description
  • uptime: Uptime in seconds
  • message_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 key
  • hop_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

  1. Hardware/Mock MeshCore → Generates raw events
  2. Event Handler → Processes and persists to database
  3. Webhook Handler → Sends HTTP POST to configured URLs (if enabled)
  4. 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.