# Show it to your users

Your user sees and uses their phone in your product, and their agent or your worker drives it with a token for that phone alone. Neither needs a NoMac account.

## A link

### TypeScript

```typescript
const { url, expires_at } = await phone.viewLink({ control: true, minutes: 120 });
```

The link is the permission: whoever opens it watches the phone, or with `control`, uses it. It works until it expires, after 2 hours by default and a day at most, or until the phone ends.

With a control link, one viewer holds input at a time and another can take over. A person's input counts as activity, so the phone does not stop as idle while your user works on it.

## In your page

### Terminal

```bash
npm install @nomac/phone
```

### React

```javascript
import { NomacPhone } from "@nomac/phone/react";

<NomacPhone url={url} onEvent={(e) => e.type === "ended" && refresh()} style={{ height: 720 }} />
```

### Any page

```javascript
import { embedPhone } from "@nomac/phone";

const phone = embedPhone(document.getElementById("phone"), url, {
  onEvent: (event) => console.log(event.type), // ready, app_launched, ended, error
});
phone.home();
phone.tap(0.5, 0.5);
const png = await phone.screenshot();
```

- The box keeps an iPhone's shape. For an iPad, pass `style={{ aspectRatio: "834 / 1210" }}`.
- `ended` comes once, when a phone that was shown ends. A link that never worked is an `error`.
- While the phone starts, the view waits for it, and after a dropped connection it reconnects by itself.
- Only view links of `https://nomac.app` are framed.

## A token for one phone

### TypeScript

```typescript
const { token } = await phone.token({ minutes: 60 });
// Hand it to your user's agent or your worker:
const theirs = new NoMacSimulator({ token });
```

An `nmp_…` token reaches that phone's tools, files, saved states, view, replay and tunnel, until it expires after 2 hours by default and a day at most. Once the phone ends, it still reads the phone and its replay. In Python: `NoMac(token=token)`.

It cannot start, list or stop phones, make another token, use the account's secrets, delete a label or reach your webhooks. It stops working when the API key that made it is revoked.

`phone.revokeTokens()` revokes every token and link the phone has so far, view, control, file and replay links included. A view already open closes within 20 seconds, and the phone keeps running. Links and tokens made afterwards work.

[Previous← A phone per user](/content/docs/platform/index.html) [Next Webhooks and billing →](/content/docs/platform/webhooks/index.html)
