Tickets

Activate a bounded, manually connected handoff session

const handoff = await rtc.tickets.issue(handoffId, {
  maxPeers: 2,
});

let peerSelected = false;
const stop = handoff.peers.watch(async (peers) => {
  if (peerSelected) return;
  const peer = peers.find((candidate) => candidate.online && candidate.ticket);
  if (!peer?.ticket) return;
  peerSelected = true;
  try {
    await handoff.peers.connect({
      deviceId: peer.deviceId,
      ticket: peer.ticket,
      scope: `ticket:${handoff.id}`,
    });
  } catch (error) {
    peerSelected = false;
    console.error(error);
  }
});

Both participants activate the same high-entropy, app-generated handoffId. The returned handle exposes scoped peers, channels, diagnostics, and close(). Issuance is device-bound, replay-protected, budget-admitted, and limited by the application manifest.

stop();
await handoff.close();

The current root API does not expose tickets.accept() or server-side ticket.revoke(). handle.token is the issuing installation's opaque OpenRTC capability. Do not display, log, or transfer it as an invitation. Share the application-owned handoffId through an authenticated product channel or a QR payload designed by your application.

Use tickets for pairing, one-time file handoff, support sessions, and explicit peer selection. A ticket admits a connection; it does not authorize a product action. Validate every requested action in your application protocol.

For one transferable invitation with automatic guest connections, set mesh: true and use tickets.join(invite). See Ticket mesh.