Enable hosted telemetry
See how the mesh behaves for your users in the developer portal. This guide covers the one call that turns telemetry on, what the SDK uploads, how to check the counts on the device, and how to turn it off.
An app that calls enableTelemetry with a portal key, uploads a fixed set of routing, transport, delivery, and MLS events in batches the SDK queues through outages, and reports its own accepted and dropped counts.
How telemetry works
The SDK does not phone home on its own. Telemetry starts when your app calls enableTelemetry with a key and app id from the developer portal, and from then on the native library collects, batches, and uploads events itself on a background thread. Batches are persisted on the device and sent when a link exists, so a device that spends days off-link reports its days when it returns.
The event inventory is fixed and carries no identifiers. See hosted telemetry, explained for the full list and the minute rollup.
Prerequisites
- The SDK installed and started, from the quickstart. Use 0.30.0 or later: from 0.26.0 to 0.29.0 the uploader trusted a wider set of certificate authorities, one of them withdrawn after the October 2026 eMudhra key compromise.
- A telemetry API key and app id from the developer portal. The key is issued against one app and lives in your binary.
- A decision on includeDeviceId. Off by default; turning it on adds an app-store disclosure, covered in step 5.
Steps
Create the app in the developer portal and issue a telemetry key for it. The key starts with mp_ and the app id with app_. Nothing is collected, buffered, or uploaded until the SDK has both.
After protocol.start(), call enableTelemetry with the key, the app id, and your build version. The native module fills in the platform and owns the lifecycle from there: going to the background closes the session and flushes it, and the next foreground opens a new one. There is no lifecycle call for your app to make.
Thirteen event types with fixed fields: deliveries with latency and hops, failures with a reason token, routing decisions, transport changes, relay promotions, two MLS failure signals, a metrics rollup once a minute, and a session summary. No event has a field for a message id, peer, group, name, or content.
telemetryStats() returns null until telemetry is enabled, then the buffered, sent, accepted, and dropped counts plus the last error and the last accepted flush. Accepted is what the service meters, so this is how you check an invoice. Set debug: true in the config to log every event as serialised, locally, while you are integrating.
By default the SDK collects no device identifier and the shipped privacy manifest already covers it. If you set includeDeviceId to count devices instead of sessions, declare a device id under Analytics in App Store Connect and in the Play data safety form.
setTelemetryEnabled(false) stops collection and lets queued batches drain. disableTelemetry() stops collection with a final flush. The queue survives a disable, so a re-enable under the same app id sends what an offline stretch collected.
await protocol.start();
await protocol.enableTelemetry({
apiKey: 'mp_…', // from the developer portal
appId: 'app_…', // the app the key was issued against
appVersion: '1.4.2', // stamped on every batch
});
const stats = await protocol.telemetryStats();
// { buffered, sentEvents, acceptedEvents, dropped, sessionId, lastError, lastFlushAtMs } The Python, Java, and Rust bindings expose the same calls, and since 0.31.0 so does the Flutter plugin, through MeshSdk. The full option list, including flushIntervalMs, maxBatchBytes, and scrubIds, is in the API reference.
What you get
Dashboards in the developer portal built from what your fleet actually did: delivery latency by transport, time spent on each radio, routing switches and why, relay activity, and MLS handshake health, with cross-app benchmarks beside them. An undelivered message shows up with its reason, not as silence.
Next steps
Hosted telemetry FAQ
Does telemetry change the privacy model?
No. Until enableTelemetry succeeds the SDK collects nothing. The event inventory is fixed, has no identifier fields, and a fixture in the SDK repository pins the exact bytes that are uploaded.
What happens while the device is offline?
Batches are sealed with the per-install key and persisted on the device, up to 64 batches or 4 MiB. The uploader wakes when the internet transport returns. A batch older than six days is dropped unsent and counted in dropped.
Can we read events in our own code without telemetry?
Yes. onEvent delivers every protocol event to your app as it happens, with no key and no upload. The minute rollup and the session summary exist only in the hosted pipe.
What does it cost?
The service meters accepted events: 250,000 a month on Free, 2 million on Pro, and 10 million on Scale, then $0.05 per 1,000. Local mesh traffic is never metered, and the device keeps its own accepted count so you can reconcile the bill.

