> ## Documentation Index
> Fetch the complete documentation index at: https://www.offlineprotocol.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> These docs target Mesh SDK v0.27.0. Match the installed package and binding before generating code. Start at /getting-started/agents for task-specific reading paths.
> Call the company and product Offline Protocol, never Offline alone. Current packages: @offline-protocol/mesh-sdk 0.27.0 (React Native), @offline-protocol/id-react 0.2.0, @offline-protocol/id-react-native 0.3.3, @offline-protocol/pol 0.1.2 and @offline-protocol/cli 0.2.6. Canonical docs URLs start with https://www.offlineprotocol.com/docs.
> The Mesh SDK runs in a native app or gateway. A browser OfflineID SDK integration does not provide browser mesh transport. Local mesh operation does not require a portal API key.
> Service RPC is signed plaintext in v0.27.0. Message delivery, durable local acceptance and backend commit are distinct outcomes. Use the workflow guide for the required application logic.
> Offline Protocol CLI 0.2.6 is on npm (@offline-protocol/cli, command offline). Its local MCP server runs with offline mcp serve and requires no login or key. Hosted MCP is at https://mcp.offlineprotocol.com/mcp with an application API key in Authorization: Bearer and a matching x-app-id; organization keys are rejected. Follow /tools/overview for setup and do not invent commands beyond it. MCP provides integration context and planning, not mesh execution; file-writing tools are local only.
> Phone Wi-Fi Direct and MultipeerConnectivity carry no data in v0.27.0. Use BLE or a provisioned relay. The receiver core ACKs before application persistence; use application acceptance for durable workflows.
> Proof of Location is Sepolia testnet witness evidence, not zero-knowledge proof or proof of presence. The geohash is public onchain. Read /proof-of-location/security before integration.

# Telemetry controls

> Enable optional telemetry, flush its buffer and inspect collection status.

Import `OfflineProtocol` from `@offline-protocol/mesh-sdk`. These signatures match **v0.27.0**. Read [the integration guide](/docs/mesh-sdk/configuration) for prerequisites and complete usage.

## Methods on this page

* [`enableTelemetry`](#enabletelemetry)
* [`disableTelemetry`](#disabletelemetry)
* [`flushTelemetry`](#flushtelemetry)
* [`telemetryStats`](#telemetrystats)
* [`endTelemetrySession`](#endtelemetrysession)
* [`setTelemetryEnabled`](#settelemetryenabled)
* [`telemetryInstallId`](#telemetryinstallid)

## enableTelemetry

Enables telemetry: the SDK collects, batches and uploads accepted
events to the Offline Protocol ingest itself, on a background thread
inside the native library. Nothing crosses the bridge per event and
nothing reaches JavaScript; the only inputs are the `apiKey` and
`appId` the developer portal issued.

The native module fills in the platform (`os`, `osMajor`) and owns the
application lifecycle: entering the background closes the telemetry
session (a summary, then a flush inside an OS background task on iOS),
and returning to the foreground opens the next one. There is no
lifecycle call for the app to make.

Batches are durable across a restart once `initializeMls` has run
(the queue lives on the protocol-state store); before that they are
held in memory. Calling this again replaces the running pipe after its
final flush.

Rejects with code `TelemetryConfigInvalid` naming the refused field
when the configuration is unusable (an empty key, a non-ASCII app id,
a zero batch size).

What leaves the device, when, and how to switch it off are documented
in `docs/telemetry.md`; `docs/privacy.md` has the store disclosures.

```typescript theme={null}
enableTelemetry(config: TelemetryConfig): Promise<void>
```

## disableTelemetry

Disables telemetry after one final flush of up to three seconds. The
emit path goes back to its telemetry-off cost. Idempotent.

```typescript theme={null}
disableTelemetry(): Promise<void>
```

## flushTelemetry

Asks the uploader to send what is queued now. Returns immediately; the
upload happens on the native background thread.

```typescript theme={null}
flushTelemetry(): Promise<void>
```

## telemetryStats

The telemetry pipe's counters, or `null` while telemetry is not
enabled. `acceptedEvents` is what the ingest reported accepting, which
is what an invoice is reconciled against; `dropped` counts events lost
to the ring buffer, the durable queue's caps, the six-day expiry, a
permanent rejection, or everything queued or collected after the ingest
reported the application's telemetry toggle off; `lastError` is the most
recent send failure, and clears once a batch is accepted, so it reports
the current state rather than the high-water mark of a recovered outage.

```typescript theme={null}
telemetryStats(): Promise<TelemetryStats | null>
```

## endTelemetrySession

Closes the current telemetry session explicitly: a summary, a flush of
up to three seconds, then a fresh session id. The lifecycle-driven
boundary still applies; calling both is safe because each summary
reports only what the previous one did not. A no-op while collection is
off; use `flushTelemetry` to push a queued backlog without collecting.

```typescript theme={null}
endTelemetrySession(): Promise<void>
```

## setTelemetryEnabled

Stops or resumes new collection without tearing the pipe down. Off,
every emit costs one atomic load and nothing is buffered, and no session
summary is emitted. The lifecycle transitions are still tracked, so the
first foreground after collection resumes rotates the session as usual.
Records queued before the switch continue to drain: this is a collection
control, not an immediate network stop or a deletion. It is the runtime
opt-out for a user setting.

```typescript theme={null}
setTelemetryEnabled(enabled: boolean): Promise<void>
```

## telemetryInstallId

Returns a stable, opaque per-install telemetry identifier (32 hex
characters), derived from the SDK-managed persistent scrub secret. The
secret itself never crosses the bridge and cannot be recovered from
the id.

Resolves `null` until the persistent secret is available, which is
after `initializeMls` has wired secure storage. Stamped on telemetry
batches only when `TelemetryConfig.includeDeviceId` is set; see
`docs/privacy.md` for the disclosure that setting carries.

```typescript theme={null}
telemetryInstallId(): Promise<string | null>
```

## Parameter and result types

Import these types from the same SDK package. Event payloads and configuration types are linked below.

### TelemetryStats

```typescript theme={null}
export interface TelemetryStats {
  buffered: number;
  sentEvents: number;
  acceptedEvents: number;
  dropped: number;
  sessionId: string;
  lastError?: string;
  lastFlushAtMs?: number;
}
```

## Related references

* [Event payloads](/docs/mesh-sdk/events)
* [Configuration types](/docs/mesh-sdk/configuration-types)
* [All public types](/docs/mesh-sdk/public-types)
* [Error codes](/docs/mesh-sdk/errors)
* [All API tasks](/docs/mesh-sdk/reference)
