Meetings can be restricted in several ways. One option is to hand the decision to a service of your own, so that who may join is governed by the rules your systems already enforce, whether those rules live in a customer portal, a patient record, or a case file.
This page describes how to build that service.
If you are using an AI coding assistant, copy the text below into it and add a sentence describing what you want to build. AI assistants accessing this page receive a separate, token-optimized version of our full developer documentation, specifically tailored by our engineers for AI coding assistants.
Before writing any code, read this page:
https://www.veeting.com/en/developer-documentation/external-meeting-authorization-service
It documents how to authorize meeting participants with my own
service. Keep these five rules in mind:
1. The token exchange is server to server. The URL contains a shared
secret, so never call it from a browser and never log it.
2. Check responseCode 0 on the exchange, not just HTTP 200.
3. Redirect back to /meeting/<MEETING-TOKEN>/join with
meetingAccessToken as a query parameter.
4. The exchange uses the 24 character meetingId. The redirect back
uses the dashed meetingToken. They are not interchangeable.
5. The request token proves the platform sent the person to me. It
does NOT authenticate them. I still have to do that.
What I want to build:The flow is a three-legged redirect, similar in shape to OAuth.
The request token proves the platform sent the participant to you. The access token proves you sent them back.
Implement an endpoint that responds to HTTP GET. We redirect the browser to it with at least these query parameters:
| Parameter | Description |
|---|---|
| hostname | The hostname of the meeting platform, for example meeting.example.org |
| meetingId | The 24-character meeting ID, for example 5f521a93c20ff6721fbb6a6c |
| meetingToken | The dashed meeting number, for example 0000-0000-0000-0000 |
| requestToken | A long random string that is valid for this meeting only |
We may append additional parameters, so read the ones you need by name rather than by position.
If your endpoint is https://external.example.org/auth, the browser arrives at:
https://external.example.org/auth?hostname=webmeeting.example.com&meetingId=5f521a93c20ff6721fbb6a6c&meetingToken=8320-2640-2482-3499&requestToken=dedf1722-661f-4004-9aaf-d3e56c498859-a27fd10f-b697-4c83-bca0-cb764cfd6c43After you decide that the participant may join, call us to exchange the request token for an access token:
GET https://<HOSTNAME>/api/v6/meeting-room/auth/<SECRET>/access-token/<MEETING-ID>/<REQUEST-TOKEN>| Placeholder | Value |
|---|---|
| HOSTNAME | The hostname from the redirect |
| SECRET | The shared secret you configured (see below) |
| MEETING-ID | The 24-character meetingId from the redirect |
| REQUEST-TOKEN | The requestToken from the redirect |
We check that the request token was issued for that meeting. On success:
{
"responseCode": 0,
"data": {
"meetingId": "5f521a93c20ff6721fbb6a6c",
"accessToken": "81430667-540e-4755-b32a-b5c51f704c7b-03526573-1494-48fb-a648-e80073275976"
}
}This call follows the usual REST API conventions, so check responseCode as well as the HTTP status and read the token from data.accessToken. See API usage for the response envelope.
This call carries your secret in the URL. Make the call server to server, never from the browser, and never log the full URL.
Send the browser to the meeting room with the access token attached:
https://<HOSTNAME>/meeting/<MEETING-TOKEN>/join?meetingAccessToken=<ACCESS-TOKEN>| Placeholder | Value |
|---|---|
| HOSTNAME | The hostname from the redirect |
| MEETING-TOKEN | The dashed meeting number from the redirect, not the 24-character one |
| ACCESS-TOKEN | The accessToken you just received |
You can add query parameters to smooth the arrival, most usefully the values you already know from authenticating the person:
https://<HOSTNAME>/meeting/<MEETING-TOKEN>/join?meetingAccessToken=<ACCESS-TOKEN>&participantName=<NAME>&participantEmail=<EMAIL>In Platform Settings, open System Configuration, then Meeting Room, and set the default authentication type for meetings to External Service. Two fields appear.

Enter the full URL of your endpoint in "URL of external authentication server" and your chosen secret in "API Key of external authentication server". The secret is stored encrypted, and every token exchange is verified against it.
The secret is yours to invent. Treat it like a password: long, random, and rotated if it ever leaks.
const express = require("express");
const app = express();
const port = 3000;
// Invent this yourself and configure the same value in the platform.
const SECRET = process.env.VEETING_SHARED_SECRET;
app.get("/auth", async (req, res) => {
const { hostname, meetingId, meetingToken, requestToken } = req.query;
// Decide here whether this person may join, using your own session,
// directory or customer database. Redirect them away if they may not.
if (!(await mayJoin(req, meetingId))) {
return res.status(403).send("Not authorized to join this meeting");
}
// Server to server: this URL contains the shared secret.
const url = `https://${hostname}/api/v6/meeting-room/auth/${SECRET}`
+ `/access-token/${meetingId}/${requestToken}`;
const response = await fetch(url).then((r) => r.json());
// HTTP 200 is not enough on its own, check responseCode too.
if (response.responseCode !== 0) {
return res.status(502).send("Could not obtain an access token");
}
const accessToken = response.data.accessToken;
res.redirect(`https://${hostname}/meeting/${meetingToken}/join`
+ `?meetingAccessToken=${encodeURIComponent(accessToken)}`);
});
app.listen(port);/meeting/<MEETING-TOKEN>/join.meetingId in the redirect back, which needs the dashed meetingToken. The exchange call is the other way around.responseCode.Contact our team to discuss the details.