I have searched the existing issues and discussions.
I am using the latest version of Open WebUI.
Installation Method
Docker
Open WebUI Version
v0.6.5
Ollama Version (if applicable)
0.6.5
Operating System
Docker
Browser (if applicable)
No response
Confirmation
I have read and followed all instructions in README.md.
I am using the latest version of both Open WebUI and Ollama.
I have included the browser console logs.
I have included the Docker container logs.
I have listed steps to reproduce the bug in detail.
Expected Behavior
When using the book_zoom_meeting() method, the system should:
Successfully validate the provided meeting parameters (topic, date, time, duration, etc.)
Format the start time correctly for the Zoom API
Make an API request to Zoom to create the new meeting
Return a formatted string containing the meeting details, including:
Topic
Date and time
Duration
Meeting ID
Join URL
Password status
Account information
The function should handle all input validation gracefully and return appropriate error messages for invalid inputs rather than throwing a type error. The core functionality should create a new Zoom meeting that appears in the user's Zoom account and can be accessed via the returned join URL.
This expected behavior would match the successful implementation of the existing get_upcoming_zoom_meetings() method, which correctly interacts with the Zoom API and returns formatted data.
Actual Behavior
After adding the Zoom booking functionality to my Zoom Meetings plugin, the system is throwing a type error when attempting to book a meeting.
Original Implementation (Working)
The original implementation (v0.1.0) provided only meeting listing functionality and worked properly:
After adding the booking functionality, i am receiving a type error:
# Added new helper functions:# - _validate_time_input()# - _book_zoom_meeting()# Added to Tools class:defbook_zoom_meeting(self,topic:str,date:str,time:str,duration:Union[int,str],agenda:str="",user:str="me",password:str=None)->str:# Implementation details...# Attempts to book a meeting and return formatted details
Changes Implemented
Added type hint imports: Optional and Union from typing
Added json module import
Added new helper functions:
_validate_time_input(): For date/time validation and formatting
_book_zoom_meeting(): Core function to create Zoom meetings via API
Added new public method to Tools class:
book_zoom_meeting(): User-facing method with parameter validation
Steps to Reproduce
Load the Keyless Zoom Meetings plugin v0.1.1
Attempt to book a meeting with the following parameters:
"""title: Keyless Zoom Meetings
author: spyci
author_url: https://github.com/open-webui
funding_url: https://github.com/open-webui
version: 0.1.0
"""
import base64
import datetime as _dt
import requests
from typing import Dict, Any, List
# --------------------------------------------------------------------------- #
# ⚙️ Hard-coded credentials supplied by the user (server-to-server OAuth) #
# --------------------------------------------------------------------------- #
ACCOUNT_ID = "insertYours"
CLIENT_ID = "insertYours"
CLIENT_SECRET = "insertYours"
# --------------------------------------------------------------------------- #
# 🛠️ Helper functions #
# --------------------------------------------------------------------------- #
def _get_zoom_token() -> str:
"""
Exchange the account credentials for a short-lived bearer token.
"""
auth_header = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
headers = {
"Authorization": f"Basic {auth_header}",
"Content-Type": "application/x-www-form-urlencoded",
}
payload = {
"grant_type": "account_credentials",
"account_id": ACCOUNT_ID,
}
resp = requests.post("https://zoom.us/oauth/token", headers=headers, data=payload)
resp.raise_for_status()
return resp.json()["access_token"] # expires in ~1 hour
def _fetch_upcoming_meetings(
token: str, user_id: str = "me", page_size: int = 30
) -> List[Dict[str, Any]]:
"""
Retrieve *all* upcoming meetings for the given user (may paginate).
"""
url = f"https://api.zoom.us/v2/users/{user_id}/meetings"
headers = {"Authorization": f"Bearer {token}"}
params = {"type": "upcoming", "page_size": page_size}
meetings: List[Dict[str, Any]] = []
while True:
resp = requests.get(url, headers=headers, params=params)
resp.raise_for_status()
data = resp.json()
meetings.extend(data.get("meetings", []))
next_page = data.get("next_page_token")
if not next_page:
break
params["next_page_token"] = next_page # paginate
return meetings
def _fmt_iso(iso: str, out: str = "%Y-%m-%d %I:%M %p") -> str:
"""
Render Zoom’s ISO-8601 timestamp in a friendlier local form.
"""
return _dt.datetime.fromisoformat(iso.replace("Z", "+00:00")).strftime(out)
# --------------------------------------------------------------------------- #
# 🧰 Public tool class (mirrors Keyless Weather style) #
# --------------------------------------------------------------------------- #
class Tools:
def __init__(self):
# Open WebUI checks this flag to decide whether to append sources
self.citation = True
def get_upcoming_zoom_meetings(self, user: str = "me") -> str:
"""
Return a human-readable description of all upcoming Zoom meetings.
:param user: Zoom user ID e.g. "me" or an email / userId.
Defaults to "me" for the authenticated account.
:return: Formatted markdown for the LLM to speak back.
"""
# 1️⃣ Get bearer token
try:
token = _get_zoom_token()
except Exception as e:
return f"Error retrieving Zoom access token: {e}"
# 2️⃣ Query meetings
try:
raw_meetings = _fetch_upcoming_meetings(token, user_id=user)
except Exception as e:
return f"Error fetching Zoom meetings: {e}"
if not raw_meetings:
return "No upcoming Zoom meetings found."
# 3️⃣ Transform into an easy-to-render dict
meetings_map = {
_fmt_iso(m["start_time"]): {
"topic": m["topic"],
"duration": f"{m['duration']} min",
"meeting_id": m["id"],
"join_url": m["join_url"],
}
for m in raw_meetings
}
# 4️⃣ Summarise
n = len(meetings_map)
return f"""
Provide a table of the upcoming Zoom meetings for **{user}**:\
{meetings_map}
Include one summary sentence noting there {'is' if n == 1 else 'are'} {n} upcoming meeting{'s' if n != 1 else ''} in total.
"""
not_working_anymore.py:
"""title: Keyless Zoom Meetings
author: spyci
author_url: https://github.com/open-webui
funding_url: https://github.com/open-webui
version: 0.1.1
"""
import base64
import datetime as _dt
import json
import requests
from typing import Dict, Any, List, Optional, Union
# --------------------------------------------------------------------------- #
# ⚙️ Hard-coded credentials supplied by the user (server-to-server OAuth) #
# --------------------------------------------------------------------------- #
ACCOUNT_ID = "insertYours"
CLIENT_ID = "insertYours"
CLIENT_SECRET = "insertYours"
# --------------------------------------------------------------------------- #
# 🛠️ Helper functions #
# --------------------------------------------------------------------------- #
def _get_zoom_token() -> str:
"""
Exchange the account credentials for a short-lived bearer token.
"""
auth_header = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
headers = {
"Authorization": f"Basic {auth_header}",
"Content-Type": "application/x-www-form-urlencoded",
}
payload = {
"grant_type": "account_credentials",
"account_id": ACCOUNT_ID,
}
resp = requests.post("https://zoom.us/oauth/token", headers=headers, data=payload)
resp.raise_for_status()
return resp.json()["access_token"] # expires in ~1 hour
def _fetch_upcoming_meetings(
token: str, user_id: str = "me", page_size: int = 30
) -> List[Dict[str, Any]]:
"""
Retrieve *all* upcoming meetings for the given user (may paginate).
"""
url = f"https://api.zoom.us/v2/users/{user_id}/meetings"
headers = {"Authorization": f"Bearer {token}"}
params = {"type": "upcoming", "page_size": page_size}
meetings: List[Dict[str, Any]] = []
while True:
resp = requests.get(url, headers=headers, params=params)
resp.raise_for_status()
data = resp.json()
meetings.extend(data.get("meetings", []))
next_page = data.get("next_page_token")
if not next_page:
break
params["next_page_token"] = next_page # paginate
return meetings
def _fmt_iso(iso: str, out: str = "%Y-%m-%d %I:%M %p") -> str:
"""
Render Zoom's ISO-8601 timestamp in a friendlier local form.
"""
return _dt.datetime.fromisoformat(iso.replace("Z", "+00:00")).strftime(out)
def _validate_time_input(date_str: str, time_str: str) -> Optional[str]:
"""
Validate the date and time input and convert to ISO format.
Returns None if validation fails.
"""
try:
# Combine date and time
datetime_str = f"{date_str} {time_str}"
# Try to parse the combined string
dt_obj = _dt.datetime.strptime(datetime_str, "%Y-%m-%d %H:%M")
# Return ISO format
return dt_obj.isoformat() + "Z"
except ValueError:
return None
def _book_zoom_meeting(
token: str,
user_id: str,
topic: str,
start_time: str,
duration: int,
agenda: str = "",
password: Optional[str] = None,
settings: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""
Book a new Zoom meeting with the specified parameters.
"""
url = f"https://api.zoom.us/v2/users/{user_id}/meetings"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
# Default settings if none provided
if settings is None:
settings = {
"host_video": True,
"participant_video": False,
"join_before_host": True,
"mute_upon_entry": True,
"waiting_room": False,
"auto_recording": "none"
}
# Build payload
payload = {
"topic": topic,
"type": 2, # Scheduled meeting
"start_time": start_time,
"duration": duration,
"timezone": "UTC",
"agenda": agenda,
"settings": settings
}
# Add optional password if provided
if password:
payload["password"] = password
# Make API request
resp = requests.post(url, headers=headers, data=json.dumps(payload))
resp.raise_for_status()
return resp.json()
# --------------------------------------------------------------------------- #
# 🧰 Public tool class (mirrors Keyless Weather style) #
# --------------------------------------------------------------------------- #
class Tools:
def __init__(self):
# Open WebUI checks this flag to decide whether to append sources
self.citation = True
def get_upcoming_zoom_meetings(self, user: str = "me") -> str:
"""
Return a human-readable description of all upcoming Zoom meetings.
:param user: Zoom user ID e.g. "me" or an email / userId.
Defaults to "me" for the authenticated account.
:return: Formatted markdown for the LLM to speak back.
"""
# 1️⃣ Get bearer token
try:
token = _get_zoom_token()
except Exception as e:
return f"Error retrieving Zoom access token: {e}"
# 2️⃣ Query meetings
try:
raw_meetings = _fetch_upcoming_meetings(token, user_id=user)
except Exception as e:
return f"Error fetching Zoom meetings: {e}"
if not raw_meetings:
return "No upcoming Zoom meetings found."
# 3️⃣ Transform into an easy-to-render dict
meetings_map = {
_fmt_iso(m["start_time"]): {
"topic": m["topic"],
"duration": f"{m['duration']} min",
"meeting_id": m["id"],
"join_url": m["join_url"],
}
for m in raw_meetings
}
# 4️⃣ Summarise
n = len(meetings_map)
return f"""
Provide a table of the upcoming Zoom meetings for **{user}**:\
{meetings_map}
Include one summary sentence noting there {'is' if n == 1 else 'are'} {n} upcoming meeting{'s' if n != 1 else ''} in total.
"""
def book_zoom_meeting(
self,
topic: str,
date: str,
time: str,
duration: Union[int, str],
agenda: str = "",
user: str = "me",
password: str = None
) -> str:
"""
Book a new Zoom meeting.
:param topic: Meeting title/topic (required)
:param date: Meeting date in YYYY-MM-DD format (required)
:param time: Meeting time in 24-hour format HH:MM (required)
:param duration: Meeting duration in minutes (required)
:param agenda: Meeting description/agenda (optional)
:param user: Zoom user ID, defaults to "me" (optional)
:param password: Meeting password (optional)
:return: Formatted markdown with meeting details or error message
"""
# Validate inputs
if not topic or not date or not time:
return "Error: Meeting topic, date, and time are required."
# Convert duration to integer if provided as string
try:
duration_minutes = int(duration)
except (ValueError, TypeError):
return "Error: Duration must be a valid number of minutes."
# Validate and format the date/time
start_time = _validate_time_input(date, time)
if not start_time:
return "Error: Invalid date or time format. Please use YYYY-MM-DD for date and HH:MM for time (24-hour format)."
# Get token
try:
token = _get_zoom_token()
except Exception as e:
return f"Error retrieving Zoom access token: {e}"
# Book the meeting
try:
meeting_data = _book_zoom_meeting(
token=token,
user_id=user,
topic=topic,
start_time=start_time,
duration=duration_minutes,
agenda=agenda,
password=password
)
# Format the response
meeting_time = _fmt_iso(meeting_data["start_time"])
return f"""
Meeting successfully booked! Here are the details:
- **Topic**: {meeting_data["topic"]}
- **Time**: {meeting_time}
- **Duration**: {meeting_data["duration"]} minutes
- **Meeting ID**: {meeting_data["id"]}
- **Join URL**: {meeting_data["join_url"]}
- **Password**: {"(Protected)" if password else "(None)"}
The meeting has been created under the account for user: {user}
"""
except Exception as e:
return f"Error booking Zoom meeting: {str(e)}"
Logs & Screenshots
Additional Information
Possible Causes
Type mismatch in date/time conversion
Issue with parameter typing in the book_zoom_meeting() method
Problem with the API request payload formatting
Originally created by @heinrihs-s on GitHub (Apr 23, 2025).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/13168
### Check Existing Issues
- [x] I have searched the existing issues and discussions.
- [x] I am using the latest version of Open WebUI.
### Installation Method
Docker
### Open WebUI Version
v0.6.5
### Ollama Version (if applicable)
0.6.5
### Operating System
Docker
### Browser (if applicable)
_No response_
### Confirmation
- [x] I have read and followed all instructions in `README.md`.
- [x] I am using the latest version of **both** Open WebUI and Ollama.
- [x] I have included the browser console logs.
- [x] I have included the Docker container logs.
- [x] I have listed steps to reproduce the bug in detail.
### Expected Behavior
When using the book_zoom_meeting() method, the system should:
Successfully validate the provided meeting parameters (topic, date, time, duration, etc.)
Format the start time correctly for the Zoom API
Make an API request to Zoom to create the new meeting
Return a formatted string containing the meeting details, including:
Topic
Date and time
Duration
Meeting ID
Join URL
Password status
Account information
The function should handle all input validation gracefully and return appropriate error messages for invalid inputs rather than throwing a type error. The core functionality should create a new Zoom meeting that appears in the user's Zoom account and can be accessed via the returned join URL.
This expected behavior would match the successful implementation of the existing get_upcoming_zoom_meetings() method, which correctly interacts with the Zoom API and returns formatted data.
### Actual Behavior
After adding the Zoom booking functionality to my Zoom Meetings plugin, the system is throwing a type error when attempting to book a meeting.
## Original Implementation (Working)
The original implementation (v0.1.0) provided only meeting listing functionality and worked properly:
```python
# Helper functions included:
# - _get_zoom_token()
# - _fetch_upcoming_meetings()
# - _fmt_iso()
class Tools:
def __init__(self):
self.citation = True
def get_upcoming_zoom_meetings(self, user: str = "me") -> str:
# Implementation details...
# Returns formatted meeting list
```
## New Implementation (Error)
After adding the booking functionality, i am receiving a type error:
```python
# Added new helper functions:
# - _validate_time_input()
# - _book_zoom_meeting()
# Added to Tools class:
def book_zoom_meeting(
self,
topic: str,
date: str,
time: str,
duration: Union[int, str],
agenda: str = "",
user: str = "me",
password: str = None
) -> str:
# Implementation details...
# Attempts to book a meeting and return formatted details
```
## Changes Implemented
1. Added type hint imports: `Optional` and `Union` from typing
2. Added `json` module import
3. Added new helper functions:
- `_validate_time_input()`: For date/time validation and formatting
- `_book_zoom_meeting()`: Core function to create Zoom meetings via API
4. Added new public method to `Tools` class:
- `book_zoom_meeting()`: User-facing method with parameter validation
### Steps to Reproduce
Load the Keyless Zoom Meetings plugin v0.1.1
Attempt to book a meeting with the following parameters:
Topic: "Test Meeting"
Date: "2025-04-30"
Time: "14:00"
Duration: 30
Agenda: "Test meeting description"
works_well.py:
```
"""title: Keyless Zoom Meetings
author: spyci
author_url: https://github.com/open-webui
funding_url: https://github.com/open-webui
version: 0.1.0
"""
import base64
import datetime as _dt
import requests
from typing import Dict, Any, List
# --------------------------------------------------------------------------- #
# ⚙️ Hard-coded credentials supplied by the user (server-to-server OAuth) #
# --------------------------------------------------------------------------- #
ACCOUNT_ID = "insertYours"
CLIENT_ID = "insertYours"
CLIENT_SECRET = "insertYours"
# --------------------------------------------------------------------------- #
# 🛠️ Helper functions #
# --------------------------------------------------------------------------- #
def _get_zoom_token() -> str:
"""
Exchange the account credentials for a short-lived bearer token.
"""
auth_header = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
headers = {
"Authorization": f"Basic {auth_header}",
"Content-Type": "application/x-www-form-urlencoded",
}
payload = {
"grant_type": "account_credentials",
"account_id": ACCOUNT_ID,
}
resp = requests.post("https://zoom.us/oauth/token", headers=headers, data=payload)
resp.raise_for_status()
return resp.json()["access_token"] # expires in ~1 hour
def _fetch_upcoming_meetings(
token: str, user_id: str = "me", page_size: int = 30
) -> List[Dict[str, Any]]:
"""
Retrieve *all* upcoming meetings for the given user (may paginate).
"""
url = f"https://api.zoom.us/v2/users/{user_id}/meetings"
headers = {"Authorization": f"Bearer {token}"}
params = {"type": "upcoming", "page_size": page_size}
meetings: List[Dict[str, Any]] = []
while True:
resp = requests.get(url, headers=headers, params=params)
resp.raise_for_status()
data = resp.json()
meetings.extend(data.get("meetings", []))
next_page = data.get("next_page_token")
if not next_page:
break
params["next_page_token"] = next_page # paginate
return meetings
def _fmt_iso(iso: str, out: str = "%Y-%m-%d %I:%M %p") -> str:
"""
Render Zoom’s ISO-8601 timestamp in a friendlier local form.
"""
return _dt.datetime.fromisoformat(iso.replace("Z", "+00:00")).strftime(out)
# --------------------------------------------------------------------------- #
# 🧰 Public tool class (mirrors Keyless Weather style) #
# --------------------------------------------------------------------------- #
class Tools:
def __init__(self):
# Open WebUI checks this flag to decide whether to append sources
self.citation = True
def get_upcoming_zoom_meetings(self, user: str = "me") -> str:
"""
Return a human-readable description of all upcoming Zoom meetings.
:param user: Zoom user ID e.g. "me" or an email / userId.
Defaults to "me" for the authenticated account.
:return: Formatted markdown for the LLM to speak back.
"""
# 1️⃣ Get bearer token
try:
token = _get_zoom_token()
except Exception as e:
return f"Error retrieving Zoom access token: {e}"
# 2️⃣ Query meetings
try:
raw_meetings = _fetch_upcoming_meetings(token, user_id=user)
except Exception as e:
return f"Error fetching Zoom meetings: {e}"
if not raw_meetings:
return "No upcoming Zoom meetings found."
# 3️⃣ Transform into an easy-to-render dict
meetings_map = {
_fmt_iso(m["start_time"]): {
"topic": m["topic"],
"duration": f"{m['duration']} min",
"meeting_id": m["id"],
"join_url": m["join_url"],
}
for m in raw_meetings
}
# 4️⃣ Summarise
n = len(meetings_map)
return f"""
Provide a table of the upcoming Zoom meetings for **{user}**:\
{meetings_map}
Include one summary sentence noting there {'is' if n == 1 else 'are'} {n} upcoming meeting{'s' if n != 1 else ''} in total.
"""
```
not_working_anymore.py:
```
"""title: Keyless Zoom Meetings
author: spyci
author_url: https://github.com/open-webui
funding_url: https://github.com/open-webui
version: 0.1.1
"""
import base64
import datetime as _dt
import json
import requests
from typing import Dict, Any, List, Optional, Union
# --------------------------------------------------------------------------- #
# ⚙️ Hard-coded credentials supplied by the user (server-to-server OAuth) #
# --------------------------------------------------------------------------- #
ACCOUNT_ID = "insertYours"
CLIENT_ID = "insertYours"
CLIENT_SECRET = "insertYours"
# --------------------------------------------------------------------------- #
# 🛠️ Helper functions #
# --------------------------------------------------------------------------- #
def _get_zoom_token() -> str:
"""
Exchange the account credentials for a short-lived bearer token.
"""
auth_header = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
headers = {
"Authorization": f"Basic {auth_header}",
"Content-Type": "application/x-www-form-urlencoded",
}
payload = {
"grant_type": "account_credentials",
"account_id": ACCOUNT_ID,
}
resp = requests.post("https://zoom.us/oauth/token", headers=headers, data=payload)
resp.raise_for_status()
return resp.json()["access_token"] # expires in ~1 hour
def _fetch_upcoming_meetings(
token: str, user_id: str = "me", page_size: int = 30
) -> List[Dict[str, Any]]:
"""
Retrieve *all* upcoming meetings for the given user (may paginate).
"""
url = f"https://api.zoom.us/v2/users/{user_id}/meetings"
headers = {"Authorization": f"Bearer {token}"}
params = {"type": "upcoming", "page_size": page_size}
meetings: List[Dict[str, Any]] = []
while True:
resp = requests.get(url, headers=headers, params=params)
resp.raise_for_status()
data = resp.json()
meetings.extend(data.get("meetings", []))
next_page = data.get("next_page_token")
if not next_page:
break
params["next_page_token"] = next_page # paginate
return meetings
def _fmt_iso(iso: str, out: str = "%Y-%m-%d %I:%M %p") -> str:
"""
Render Zoom's ISO-8601 timestamp in a friendlier local form.
"""
return _dt.datetime.fromisoformat(iso.replace("Z", "+00:00")).strftime(out)
def _validate_time_input(date_str: str, time_str: str) -> Optional[str]:
"""
Validate the date and time input and convert to ISO format.
Returns None if validation fails.
"""
try:
# Combine date and time
datetime_str = f"{date_str} {time_str}"
# Try to parse the combined string
dt_obj = _dt.datetime.strptime(datetime_str, "%Y-%m-%d %H:%M")
# Return ISO format
return dt_obj.isoformat() + "Z"
except ValueError:
return None
def _book_zoom_meeting(
token: str,
user_id: str,
topic: str,
start_time: str,
duration: int,
agenda: str = "",
password: Optional[str] = None,
settings: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""
Book a new Zoom meeting with the specified parameters.
"""
url = f"https://api.zoom.us/v2/users/{user_id}/meetings"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
# Default settings if none provided
if settings is None:
settings = {
"host_video": True,
"participant_video": False,
"join_before_host": True,
"mute_upon_entry": True,
"waiting_room": False,
"auto_recording": "none"
}
# Build payload
payload = {
"topic": topic,
"type": 2, # Scheduled meeting
"start_time": start_time,
"duration": duration,
"timezone": "UTC",
"agenda": agenda,
"settings": settings
}
# Add optional password if provided
if password:
payload["password"] = password
# Make API request
resp = requests.post(url, headers=headers, data=json.dumps(payload))
resp.raise_for_status()
return resp.json()
# --------------------------------------------------------------------------- #
# 🧰 Public tool class (mirrors Keyless Weather style) #
# --------------------------------------------------------------------------- #
class Tools:
def __init__(self):
# Open WebUI checks this flag to decide whether to append sources
self.citation = True
def get_upcoming_zoom_meetings(self, user: str = "me") -> str:
"""
Return a human-readable description of all upcoming Zoom meetings.
:param user: Zoom user ID e.g. "me" or an email / userId.
Defaults to "me" for the authenticated account.
:return: Formatted markdown for the LLM to speak back.
"""
# 1️⃣ Get bearer token
try:
token = _get_zoom_token()
except Exception as e:
return f"Error retrieving Zoom access token: {e}"
# 2️⃣ Query meetings
try:
raw_meetings = _fetch_upcoming_meetings(token, user_id=user)
except Exception as e:
return f"Error fetching Zoom meetings: {e}"
if not raw_meetings:
return "No upcoming Zoom meetings found."
# 3️⃣ Transform into an easy-to-render dict
meetings_map = {
_fmt_iso(m["start_time"]): {
"topic": m["topic"],
"duration": f"{m['duration']} min",
"meeting_id": m["id"],
"join_url": m["join_url"],
}
for m in raw_meetings
}
# 4️⃣ Summarise
n = len(meetings_map)
return f"""
Provide a table of the upcoming Zoom meetings for **{user}**:\
{meetings_map}
Include one summary sentence noting there {'is' if n == 1 else 'are'} {n} upcoming meeting{'s' if n != 1 else ''} in total.
"""
def book_zoom_meeting(
self,
topic: str,
date: str,
time: str,
duration: Union[int, str],
agenda: str = "",
user: str = "me",
password: str = None
) -> str:
"""
Book a new Zoom meeting.
:param topic: Meeting title/topic (required)
:param date: Meeting date in YYYY-MM-DD format (required)
:param time: Meeting time in 24-hour format HH:MM (required)
:param duration: Meeting duration in minutes (required)
:param agenda: Meeting description/agenda (optional)
:param user: Zoom user ID, defaults to "me" (optional)
:param password: Meeting password (optional)
:return: Formatted markdown with meeting details or error message
"""
# Validate inputs
if not topic or not date or not time:
return "Error: Meeting topic, date, and time are required."
# Convert duration to integer if provided as string
try:
duration_minutes = int(duration)
except (ValueError, TypeError):
return "Error: Duration must be a valid number of minutes."
# Validate and format the date/time
start_time = _validate_time_input(date, time)
if not start_time:
return "Error: Invalid date or time format. Please use YYYY-MM-DD for date and HH:MM for time (24-hour format)."
# Get token
try:
token = _get_zoom_token()
except Exception as e:
return f"Error retrieving Zoom access token: {e}"
# Book the meeting
try:
meeting_data = _book_zoom_meeting(
token=token,
user_id=user,
topic=topic,
start_time=start_time,
duration=duration_minutes,
agenda=agenda,
password=password
)
# Format the response
meeting_time = _fmt_iso(meeting_data["start_time"])
return f"""
Meeting successfully booked! Here are the details:
- **Topic**: {meeting_data["topic"]}
- **Time**: {meeting_time}
- **Duration**: {meeting_data["duration"]} minutes
- **Meeting ID**: {meeting_data["id"]}
- **Join URL**: {meeting_data["join_url"]}
- **Password**: {"(Protected)" if password else "(None)"}
The meeting has been created under the account for user: {user}
"""
except Exception as e:
return f"Error booking Zoom meeting: {str(e)}"
```
### Logs & Screenshots


### Additional Information
Possible Causes
Type mismatch in date/time conversion
Issue with parameter typing in the book_zoom_meeting() method
Problem with the API request payload formatting
GiteaMirror
added the bug label 2026-05-20 21:42:22 -05:00
Please adjust the title for this issue to be descriptive of the issue at a quick glance.
<!-- gh-comment-id:2824692401 -->
@silentoplayz commented on GitHub (Apr 23, 2025):
Please adjust the title for this issue to be descriptive of the issue at a quick glance.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @heinrihs-s on GitHub (Apr 23, 2025).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/13168
Check Existing Issues
Installation Method
Docker
Open WebUI Version
v0.6.5
Ollama Version (if applicable)
0.6.5
Operating System
Docker
Browser (if applicable)
No response
Confirmation
README.md.Expected Behavior
When using the book_zoom_meeting() method, the system should:
Successfully validate the provided meeting parameters (topic, date, time, duration, etc.)
Format the start time correctly for the Zoom API
Make an API request to Zoom to create the new meeting
Return a formatted string containing the meeting details, including:
Topic
Date and time
Duration
Meeting ID
Join URL
Password status
Account information
The function should handle all input validation gracefully and return appropriate error messages for invalid inputs rather than throwing a type error. The core functionality should create a new Zoom meeting that appears in the user's Zoom account and can be accessed via the returned join URL.
This expected behavior would match the successful implementation of the existing get_upcoming_zoom_meetings() method, which correctly interacts with the Zoom API and returns formatted data.
Actual Behavior
After adding the Zoom booking functionality to my Zoom Meetings plugin, the system is throwing a type error when attempting to book a meeting.
Original Implementation (Working)
The original implementation (v0.1.0) provided only meeting listing functionality and worked properly:
New Implementation (Error)
After adding the booking functionality, i am receiving a type error:
Changes Implemented
OptionalandUnionfrom typingjsonmodule import_validate_time_input(): For date/time validation and formatting_book_zoom_meeting(): Core function to create Zoom meetings via APIToolsclass:book_zoom_meeting(): User-facing method with parameter validationSteps to Reproduce
Load the Keyless Zoom Meetings plugin v0.1.1
Attempt to book a meeting with the following parameters:
Topic: "Test Meeting"
Date: "2025-04-30"
Time: "14:00"
Duration: 30
Agenda: "Test meeting description"
works_well.py:
not_working_anymore.py:
Logs & Screenshots
Additional Information
Possible Causes
Type mismatch in date/time conversion
Issue with parameter typing in the book_zoom_meeting() method
Problem with the API request payload formatting
@silentoplayz commented on GitHub (Apr 23, 2025):
Please adjust the title for this issue to be descriptive of the issue at a quick glance.