Custom tools put your own interface inside the meeting room, alongside video, documents, and the whiteboard. A tool is an icon, a label, and one of your pages displayed in an iFrame.
You configure them in the system settings of a white-label instance: one configuration per instance, and none by default.
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/custom-tools
It documents custom tools in the Veeting Rooms meeting room.
Keep these five rules in mind:
1. An API endpoint must return a BARE JSON array of tools, not an
object with a data property.
2. meetingId is the 24 character id and meetingToken is the dashed
number. Do not swap them.
3. A fixed iFrame URL receives culture but never moderatorToken. An
API endpoint receives moderatorToken but never culture.
4. moderatorToken is always appended to the API call, so its presence
proves nothing. Validate the value itself.
5. At most five tools are shown, and a tool without an iFrameUrl is
skipped.
What I want to build:There are two ways to supply a tool, and each instance uses one of them.
| Source | What it does | Use it when |
|---|---|---|
| iFrame URL | One fixed URL, shown to everyone | The tool is the same for every participant |
| API endpoint | We call your endpoint for each participant, and you return the tools they should see | Tools differ per participant, or you want more than one |
Whichever you choose, the tool must be enabled for the instance before anything appears.

The URL must be served over HTTPS, and your web server must send headers that let a browser display it inside our page.
The label is either a fixed string or a pipe-separated list of translations.
| Label | Result |
|---|---|
| My Custom Tool | Always reads "My Custom Tool", whatever language the meeting room is in. |
| en:My Custom Tool|de-CH:Mein eigenes Tool|fr:Mon outil personnalise | English shows "My Custom Tool", German shows "Mein eigenes Tool", and so on. A language not in the list falls back to the English entry if there is one, otherwise to the first entry. |
We add query parameters so your page knows who is looking at it:
| Parameter | Value |
|---|---|
| participantName | The participant's name |
| participantId | The unique ID of the meeting participant |
| meetingId | The 24-character meeting ID, for example 5349b4ddd2781d08c09890f3 |
| meetingToken | The dashed meeting number, for example 0000-0000-0000-0000 |
| culture | The participant's locale when they entered the room, for example en, en-US, or de-DE |
Two things to know:
moderatorToken is not sent here. It is only sent to an API endpoint (see below). A fixed iFrame cannot tell whether the viewer is a moderator.?, the parameters are appended with &, so a URL with its own query string keeps working.Values are URL-encoded, so decode them before use. A participant name containing a space or an ampersand arrives intact.
An API endpoint decides which tools each participant sees, and it can return up to five.

When someone joins, we call your endpoint and show them whatever it returns.
We send an HTTP GET with your configured secret in an X-API-KEY header:
| Parameter | Value |
|---|---|
| participantName | The participant's name |
| participantId | The unique ID of the meeting participant |
| meetingId | The 24-character meeting ID |
| meetingToken | The dashed meeting number |
| moderatorToken | The participant's moderator token |
Note:
cultureis not sent to an API endpoint, andmoderatorTokenis always appended. For a participant who is not a moderator, it carries no valid token, so validate the value itself instead of relying on the parameter being present. Values are URL-encoded.
curl 'https://<CUSTOM-TOOL-API-URL>?participantName=Joe%20Doe\
&participantId=XXXXX\
&meetingId=5349b4ddd2781d08c09890f3\
&meetingToken=0000-0000-0000-0000\
&moderatorToken=YYYYY' \
-H 'X-API-KEY: <CUSTOM-TOOL-API-KEY>' \
-H 'accept: application/json, text/plain, */*'Respond with HTTP 200 and a bare JSON array of tool objects. Do not wrap it in an envelope: unlike the REST API, nothing here unwraps a data property for you.
| Property | Meaning |
|---|---|
| iFrameUrl | The URL to display. A tool without one is skipped. |
| toolIcon | An SVG string for the icon. Anything longer than 50,000 characters is dropped, and the tool falls back to the default icon. |
| labels | An array of label objects |
A label object:
| Property | Meaning |
|---|---|
| culture | The locale of this label, for example en, en-US, or de-DE |
| label | The text to display, for example "My Custom Tool" |
[
{
"iFrameUrl": "https://www.example.com/custom-tool-1",
"toolIcon": "<svg>...</svg>",
"labels": [
{
"culture": "en-US",
"label": "Custom tool 1"
},
{
"culture": "de",
"label": "Spezialtool 1"
}
]
}
]iFrameUrl is skipped entirely.labels is empty or missing, the tool is labeled "Custom tool".meetingId and meetingToken. meetingId is the 24-character one; meetingToken is the dashed one.moderatorToken on a fixed iFrame URL, where it is never sent.culture at an API endpoint, where it is never sent.moderatorToken as proof the participant is a moderator.Contact our team to discuss the details.