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.

What you will build

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

Steps

1
Get a key from the portal

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.

2
Call enableTelemetry

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.

3
Know what leaves the device

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.

4
Check telemetryStats

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.

5
Decide the disclosures

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.

6
Turn it off when you need to

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.

TypeScript
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.

See what your fleet does off-link. One call. Nothing before it.