Video Visits (Telehealth)
Video visits add a private, one-to-one video call to any custom app — a clinician and a patient, an advisor and a client, an inspector and a homeowner. A tool of your app creates the visit and a join link for each person; the app shows the built-in call screen. There is nothing to install, host or configure.
What it's for
- Telehealth and appointments. A patient joins from your patient portal and the clinician from your staff app, at the appointment time.
- Any one-to-one video meeting that belongs inside your own app rather than a separate meeting product, with your app deciding who may join.
Each visit has exactly two seats: one host (the clinician or staff member) and one guest (the patient or visitor).
Key concepts
- Visit (room) — one video call. Your tool creates it, usually tied to your own record with an
externalRefsuch as an appointment ID. Creating a visit with anexternalRefthat already has an open visit returns that same visit, so it's safe to call every time someone opens the appointment. - Join link (token) — an opaque string that lets one person into one seat of one visit. Your tool issues it; your app passes it to the call screen. A link works again and again until it expires, so a dropped connection or a page refresh simply rejoins, but always as the same person: opening the same guest link on a second device moves the guest to that device instead of adding a third person.
- Expiry — visits last 4 hours by default (up to 30 days); links last 2 hours by default (up to 7 days) and never outlast their visit. When a visit ends or expires, every link to it stops working and both people are disconnected.
- Who can create visits — only your tools. Visits belong to the company the tool runs in, including when one of your app's visitors runs the tool, and nothing in the browser can create a visit or a link on its own.
How to add video visits to an app
-
Create a tool that returns a join link. In an AUTESSA_SCRIPT tool, create (or reuse) the visit and issue a link for the person asking. Decide here who is allowed in: for example, give the guest link only to the patient on that appointment, and the host link only to staff.
const appointmentId = variables.appointment_id;const room = autessa.telehealth.createRoom({ externalRef: "appt-" + appointmentId, ttlMinutes: 120 });const link = autessa.telehealth.issueJoin({roomId: room.roomId,role: "GUEST", // "HOST" for the clinician's linkdisplayName: "Pat Doe", // shown to the other personttlMinutes: 90});response.setResponse(JSON.stringify({ token: link.token, expiresAt: link.expiresAt })); -
Allow the app to run the tool. Add the tool to the app's runtime permissions (Settings → Permissions) so the page can call it.
-
Show the call screen. When the person opens the visit, call the tool, then render the built-in component with the token:
// from a page in src/pagesimport { TelehealthCall } from '../autessa/components';<TelehealthCalltoken={token}title="Video visit with Dr. Lee"onEnd={() => navigate('/appointments')}/>Or ask AutoBot: "add a video visit button to the appointment page that opens a call with the patient."
-
End the visit when it's over (optional — visits also end on their own when they expire). Ending disconnects both people and cancels their links:
autessa.telehealth.endRoom({ roomId: variables.room_id });
The call screen
TelehealthCall is a complete visit screen, built into every app:
- A pre-join check with a camera preview, microphone and camera toggles, and camera and microphone pickers, so people fix their setup before the other person sees them.
- The other person's video, with your own camera as a small self view.
- Mute, camera on/off, devices (camera, microphone and, where the browser supports it, speaker) and leave controls.
- A waiting state ("Waiting for Dr. Lee to join") until the other person arrives. Either person can join first.
- A connection quality indicator, and automatic reconnection after a network drop or page refresh.
- Plain-language messages for expired links, ended visits and blocked cameras or microphones.
- Name
token- Type
- string
- Description
The join link token from your tool.
- Name
title- Type
- string, optional
- Description
Shown above the call, for example "Video visit with Dr. Lee".
- Name
showPreJoin- Type
- boolean, optional
- Description
Show the pre-join check with a Join button first. Defaults to
true; withfalsethe call starts as soon as the screen opens.
- Name
waitingMessage- Type
- string, optional
- Description
Replaces the "Waiting for the other person to join" message.
- Name
joinLabel- Type
- string, optional
- Description
Text of the Join button. Defaults to "Join visit".
- Name
onEnd- Type
- (reason: 'left' | 'ended') => void, optional
- Description
Called when this person leaves (
left), or when the visit ends or the link stops working (ended).
- Name
onError- Type
- (error: Error) => void, optional
- Description
Called with problems such as an invalid link or a blocked camera. The screen shows them too.
- Name
onStateChange- Type
- (state: string) => void, optional
- Description
connecting,waiting,connected,reconnecting,endedorfailed.
- Name
height- Type
- number | string, optional
- Description
Height of the call area. Defaults to 560 pixels.
Building your own call screen
For a fully custom layout, use the Telehealth service from src/autessa/services instead of the component. Telehealth.join(token, options) asks for the camera and microphone, connects, and returns a session with:
- Name
localStream / remoteStream- Type
- MediaStream
- Description
Your camera and microphone (show it muted), and the other person's audio and video. Attach them to
videoelements.
- Name
state- Type
- string
- Description
connecting,waiting,connected,reconnectingorended. PassonStateChangein the options to be told when it changes.
- Name
setMicrophoneEnabled / setCameraEnabled- Type
- (enabled: boolean) => void
- Description
Mute or unmute, and turn the camera off or on. The other person is told, so their screen can show "camera off".
- Name
listDevices / switchDevice- Type
- functions
- Description
List cameras, microphones and speakers, and switch camera or microphone mid-call.
- Name
quality- Type
- object
- Description
good,fairorpoor, with round-trip time and packet loss. PassonQualityin the options for updates.
- Name
end- Type
- () => void
- Description
Leave the visit and turn off the camera and microphone.
Telehealth.fetchJoin(token) checks a link without connecting and returns the seat (HOST or GUEST), both display names and when the link and visit expire. Telehealth.getLocalMedia() starts the camera for a preview you build yourself.
Script reference
The same functions are available as autessa.telehealth.* (arguments and results are objects) and as the telehealth helper (results are JSON strings, like the other helpers).
- Name
autessa.telehealth.createRoom- Type
- (args) => room
- Description
Arguments:
externalRef(optional, up to 200 characters) andttlMinutes(optional, default 240, up to 43200). ReturnsroomId,externalRef,status(OPENorENDED),createdAt,expiresAtandendedAt. Reuses an open visit with the sameexternalRef, extending it if you ask for a longer time.
- Name
autessa.telehealth.issueJoin- Type
- (args) => link
- Description
Arguments:
roomId,role(HOSTorGUEST),displayName(optional, shown to the other person) andttlMinutes(optional, default 120, up to 10080). Returnstoken,roomId,role,displayNameandexpiresAt.
- Name
autessa.telehealth.endRoom- Type
- (args) => room
- Description
Argument:
roomId. Ends the visit for both people and cancels its links.
- Name
autessa.telehealth.getRoom- Type
- (args) => room
- Description
Argument:
roomId. Returns the visit, including whether it is still open.
Failures throw with a plain message. Codes: INVALID_REQUEST (a missing or invalid argument), ROOM_NOT_FOUND, VISIT_ENDED (issuing a link for a visit that has ended), NO_COMPANY (the script isn't running as part of a company tool run) and UNAVAILABLE (try again shortly).
People joining see these messages: "This visit link isn't valid", "This visit link has expired", "This visit link was cancelled", and "This video visit has ended". Ask your tool for a new link in the first three cases.
Privacy and security
- Calls are not recorded or stored by Autessa. Audio and video travel directly between the two browsers, or, when a network blocks direct connections, through an encrypted relay that forwards them without storing them. Media is always encrypted in transit.
- Recording is up to your app. If you add recording, get each person's consent first and tell them where the recording is kept.
- Links are secrets. Anyone holding a link can take that seat until it expires. Issue links only to the right person, keep their lifetime short, never log them, never store them in tables, and never put them in URLs you share or log. Autessa keeps only a fingerprint of each link, never the link itself.
- Only your tools can create visits and links, so your app's own rules decide who joins.
- Join attempts are rate-limited, and links are long random strings that can't be guessed.
Browser support
Current versions of Chrome, Edge, Safari and Firefox on desktop, iOS and Android. People are asked to allow the camera and microphone the first time; if they decline, the call screen explains how to allow them.