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

# Live inspection

> Watch one of your own testers' devices live while the app is open, with their consent, an indicator on their screen, and nothing stored.

Live inspection lets your team watch the device of one of your own testers while the app is
open: the log lines it writes, its memory and power state, and masked wireframes of the screen.
Your team can also send it three commands. It is meant for your internal and test builds: a
tester reproduces a bug while you watch, instead of describing it later.

Nothing streams from anyone else's device. Live inspection needs two keys, and the device shows
when it is being watched.

## The two keys

A device takes part only when both are turned:

1. **The project marks it as an internal tester.** An owner or admin marks a person in
   [People](https://docs.apsio.io/concepts/people.md#internal-testers), for up to a year. The API can also mark one
   install.
2. **The app allows it on the device.** The app calls `setLiveInspection(true)`, behind its own
   setting ("Let my team see my activity live"). It is off until the app turns it on, and the SDK
   keeps the choice across launches until the app turns it off. Nothing else turns it on: not
   the policy, not a command, not Apsio. An app that never calls it never takes part, so
   production builds stay out by default.

The call, and how to read the choice back, is on each SDK: [iOS](https://docs.apsio.io/sdks/ios.md#live-inspection),
[Android](https://docs.apsio.io/sdks/android.md#live-inspection) and [React Native](https://docs.apsio.io/sdks/react-native.md#live-inspection).
It can be made before `start`. The Flutter SDK has no live inspection yet
([why](https://docs.apsio.io/sdks/flutter.md#what-this-version-does-not-do)).

Even with both keys, the device goes live only while:

* the user's [consent](https://docs.apsio.io/concepts/privacy.md) is granted and the kill switch is off;
* the app has its installation id (an app that turns it off, `installationId: false`, never
  takes part);
* the app is in the foreground.

## What the tester sees

While anyone on your team watches, the device shows **"Your team is viewing this app live"** at the
top of the screen, above the app's content and inside the safe area. It names your team, never a
person: the device does not know who is watching. It takes no touch, and the screen reader announces
it each time it appears (on iOS, each notice too). The SDK gives the app no way to hide or restyle
it. System screens, such as alerts and the share sheet, and on iOS the app's own alert-level
windows, can cover it.

Each command that runs adds a short notice under it for 3 seconds: "Your team took a screenshot",
"Your team collected diagnostics" or "Your team raised the log level for 30 minutes".

The indicator and its notices are never recorded: replay, live wireframes, screen views and
taps leave them out.

## What your team sees

* **Log lines**: copies of the records the SDK writes for the `logs` and `errors` families,
  after redaction, whatever sampling and triggers say; each body cut to 4 KB.
* **Memory and power**: the memory footprint, the thermal state and the power saving mode, and
  the battery when the SDK's `battery` option is on (see each SDK).
* **Wireframes of the screen** when the app records [replay](https://docs.apsio.io/concepts/replay.md): full frames,
  masked exactly as replay masks them. Taking them does not change the session's replay, its
  segments or its budget.

Live inspection never sends what consent, an opt-out or the kill switch stopped. It sends no
log lines or wireframes of a family the app turned off in code or the policy sets to never, and
refuses `diagnostics` while the `logs` family is off.

## Commands

Owners and admins can send a device in a live session one of three commands. None runs code or
changes the app's state, and each shows its notice on the device when it runs.

| Command | What it does |
| - | - |
| `screenshot` | One masked wireframe of the current screen, never pixels. It goes to the people watching, and is never stored. Refused or failed when the app is not recording replay, or there is no screen to capture |
| `diagnostics` | One `apsio.diagnostics` record of the device's state: memory, storage (app, data, cache), thermal state, connection type and the SDK's queue. It goes through ingest and is stored like any record. Refused while the `logs` family is off |
| `raise_log_level` | For 30 minutes, the SDK writes log records from `DEBUG` up and sends every record of `logs`, `spans` and `network` whatever sampling says. In memory only: it ends after 30 minutes, at the next launch, or when consent, live inspection or the kill switch withdraws it |

Records released only because of a command carry `apsio.sampling.released` = `live`, and are
stored, kept and erased like every other record.

## When it pauses and ends

The channel runs in the foreground only; nothing is kept or scheduled in the background. It
**pauses** while the app is interrupted (for 2 seconds or more), and while the device saves
power or data: Low Power Mode and Low Data Mode on iOS, Battery Saver and Data Saver on Android.
Under Low Data Mode or Data Saver the device sends nothing at all.

A live session **ends**:

* at once, when the app goes to the background, consent or live inspection is withdrawn, or the
  kill switch turns on;
* when the person stops being a tester, at the device's next check-in (within about two
  minutes);
* after 60 seconds paused;
* 30 minutes after it started, unless someone watching renews it;
* after 10 MB sent in the session.

A device sends at most 50 MB a day (UTC), a count it keeps across launches; past it, it does not
go live again until the day ends.

## Privacy

* **Nothing streamed is stored.** Log lines, metrics, wireframes and screenshots go to the people
  watching, and Apsio does not store them. Live data is never written to disk on the device:
  lines wait in memory only until the next upload, a lost upload of lines and wireframes is lost
  (the people watching see a gap), and only a command's result is sent once more after a
  failure.
* **The tester stays unnamed.** The device proves it is a tester with a one-way proof and never
  sends the user hash. Like every SDK request, live requests carry the install id. Apsio keeps
  only the tester's one-way hash and its last 4 characters, and erasing the user removes them as
  a tester.
* **People only.** Only a signed-in person watches, never a project token, an agent or an upload
  token. Any member of the organization can watch; only owners and admins send commands.
* **Audited.** Opening a view is `live.view.start`, and a command `device_command.send` and
  `device_command.result`, in the audit log (**Settings › Activity**), never with the install id,
  the user hash, a screenshot or diagnostics.
* **The connection.** HTTPS to the live host the policy names only (plain HTTP only to this
  machine, for local testing), never following a redirect, with no cache.
  The SDK sets no cookies and the live host sets none (on Android, a cookie handler the app
  installs for the whole process still applies: see [Android](https://docs.apsio.io/sdks/android.md#live-inspection)).

## Watching a device

On a tester's page in **People**, the **Live** tab opens the view. Any member of the
organization can open it, and each opening is audited as `live.view.start`. Leaving the tab
closes it.

The view shows the tester's devices, with a device picker when there are several:

* the log lines, newest first, filtered by text and lowest level, with **Pause**;
* memory and battery over the last minute (battery only with the SDK's `battery` option);
* a wireframe of the screen.

Owners and admins send the three commands from the tab. Each is confirmed before it goes, and
its result shows under it: the screenshot's wireframe, the diagnostics, or until when the log
level is raised.

The tab says why a device is not live: none online, in the background, Low Power Mode, paused or
ended. It offers **Renew** while a session is live, and when its 30 minutes or 10 MB are up. The
view itself closes after 30 minutes unless renewed.

For scripts, a signed-in person opens a view with `POST /v1/projects/{projectId}/live/tickets` and
the tester's id: the answer is a WebSocket URL to open within 60 seconds, and the view closes after
30 minutes unless renewed (30 tickets a minute per person). Owners and admins send commands with
`POST /v1/projects/{projectId}/live/commands` (10 a minute per person); the device answers within 2
minutes, and `409` means it is not in a live session. The API reference lists their fields.

How devices take part is in the specification:
[live inspection](https://spec.apsio.io/v0.1/live-inspection/).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.