# Extract the first hub ID ## What you will build In this tutorial, you will create a complete single-session virtual event for **"CloudSync Pro Launch"** a product unveiling webinar scheduled for December 15, 2025, at 2:00 PM EST. You will set up registration, configure branding, pre-register VIP attendees, and publish the event to make it live. ### Event Details - **Product:** CloudSync Pro - Next-generation cloud storage solution - **Date:** December 15, 2025, 2:00 PM - 3:00 PM EST - **Format:** Virtual webinar (up to 10,000 attendees) - **Registration:** Public with email confirmation - **Duration:** 1 hour live presentation + Q&A ## Time required 20—30 minutes ## What you will learn - Create a SIMPLE*EVENT (\_single-session*) event. - Configure webinar-style presentation settings. - Set up public registration with authentication. - Pre-register VIP attendees via API. - Publish and activate your event. --- ## Prerequisites Before starting, ensure you have: - **Account:** Zoom Pro or higher account plan - **License:** Zoom Webinars Plus or Events license - **API Access:** Server-to-Server OAuth app or OAuth app with these scopes: - `zoom_events:write:event` (or `zoom_events_basic:write:admin`) - `zoom_events:write:access_links` (or `zoom_events_access_links:write:admin`) - `zoom_events:write:ticket` (or `zoom_events_tickets:write:admin`) - **Access Token:** Valid OAuth access token (referenced as `YOUR_ACCESS_TOKEN` below) **No API credentials?** Visit the [Zoom Marketplace](https://marketplace.zoom.us/) to create an app. --- ## Step 1: Get your Hub ID Every Zoom Events event must belong to an event hub. Retrieve your hub ID. ### cURL ```shell curl -X GET "https://api.zoom.us/v2/zoom_events/hubs?role_type=host" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ### Python ```python import requests url = "https://api.zoom.us/v2/zoom_events/hubs" headers = { "Authorization": "Bearer YOUR_ACCESS_TOKEN" } params = { "role_type": "host" } response = requests.get(url, headers=headers, params=params) response.raise_for_status() # Check for HTTP errors hubs = response.json() # Extract the first hub ID hub_id = hubs["hubs"][0]["hub_id"] print(f"Hub ID: {hub_id}") ``` ### JavaScript (Node.js) ```javascript const axios = require("axios"); async function getHubId() { const url = "https://api.zoom.us/v2/zoom_events/hubs"; const headers = { Authorization: "Bearer YOUR_ACCESS_TOKEN", }; const params = { role_type: "host", }; try { const response = await axios.get(url, { headers, params }); const hubId = response.data.hubs[0].hub_id; console.log(`Hub ID: ${hubId}`); return hubId; } catch (error) { console.error( "Failed to get hub ID:", error.response?.data || error.message, ); throw error; } } getHubId(); ``` ### Expected Response ```json { "total_records": 1, "hubs": [ { "hub_id": "aBcDeFgH1234567890", "name": "My Events Hub", "hub_active": true } ] } ``` **Save this `hub_id`** - You will need it in the next step. --- ## Step 2: Create the product launch event Create the CloudSync Pro Launch event as a single-session webinar. ### cURL ```shell curl -X POST "https://api.zoom.us/v2/zoom_events/events" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{ "hub_id": "aBcDeFgH1234567890", "name": "CloudSync Pro Launch", "": "Join us for the exclusive launch of CloudSync Pro, our next-generation cloud storage solution. Discover breakthrough features, live demos, and special launch pricing available only to attendees.", "timezone": "America/New_York", "event_type": "SIMPLE_EVENT", "access_level": "PRIVATE_UNRESTRICTED", "meeting_type": "WEBINAR", "attendance_type": "VIRTUAL", "tagline": "The Future of Cloud Storage Starts Here", "contact_name": "Sarah Chen", "calendar": [ { "start_time": "2025-12-15T19:00:00Z", "end_time": "2025-12-15T20:00:00Z" } ] }' ``` ### Python ```python import requests from datetime import datetime, timezone url = "https://api.zoom.us/v2/zoom_events/events" headers = { "Content-Type": "application/json", "Authorization": "Bearer YOUR_ACCESS_TOKEN" } event_data = { "hub_id": "aBcDeFgH1234567890", "name": "CloudSync Pro Launch", "": "Join us for the exclusive launch of CloudSync Pro, our next-generation cloud storage solution. Discover breakthrough features, live demos, and special launch pricing available only to attendees.", "timezone": "America/New_York", "event_type": "SIMPLE_EVENT", "access_level": "PRIVATE_UNRESTRICTED", "meeting_type": "WEBINAR", "attendance_type": "VIRTUAL", "tagline": "The Future of Cloud Storage Starts Here", "contact_name": "Sarah Chen", "calendar": [ { "start_time": "2025-12-15T19:00:00Z", # 2 PM EST = 7 PM UTC "end_time": "2025-12-15T20:00:00Z" # 3 PM EST = 8 PM UTC } ] } response = requests.post(url, headers=headers, json=event_data) response.raise_for_status() # Check for HTTP errors event = response.json() event_id = event["event_id"] print(f"Event created. Event ID: {event_id}") print(f"Status: {event['status']}") ``` ### JavaScript (Node.js) ```javascript const axios = require('axios'); async function createEvent(hubId) { const url = 'https://api.zoom.us/v2/zoom_events/events'; const headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_ACCESS_TOKEN' }; const eventData = { hub_id: hubId, name: 'CloudSync Pro Launch', : 'Join us for the exclusive launch of CloudSync Pro, our next-generation cloud storage solution. Discover breakthrough features, live demos, and special launch pricing available only to attendees.', timezone: 'America/New_York', event_type: 'SIMPLE_EVENT', access_level: 'PRIVATE_UNRESTRICTED', meeting_type: 'WEBINAR', attendance_type: 'VIRTUAL', tagline: 'The Future of Cloud Storage Starts Here', contact_name: 'Sarah Chen', calendar: [ { start_time: '2025-12-15T19:00:00Z', // 2 PM EST = 7 PM UTC end_time: '2025-12-15T20:00:00Z' // 3 PM EST = 8 PM UTC } ] }; try { const response = await axios.post(url, eventData, { headers }); const event = response.data; console.log(`Event created. Event ID: ${event.event_id}`); console.log(`Status: ${event.status}`); return event.event_id; } catch (error) { console.error('Failed to create event:', error.response?.data || error.message); throw error; } } createEvent('aBcDeFgH1234567890'); ``` ### Expected Response ```json { "event_id": "kNqLPC6hSFiZ9NpgjA549w", "name": "CloudSync Pro Launch", "": "Join us for the exclusive launch of CloudSync Pro...", "timezone": "America/New_York", "event_type": "SIMPLE_EVENT", "status": "draft", "meeting_type": "WEBINAR", "access_level": "PRIVATE_UNRESTRICTED", "attendance_type": "VIRTUAL", "hub_id": "aBcDeFgH1234567890", "calendar": [ { "start_time": "2025-12-15T19:00:00Z", "end_time": "2025-12-15T20:00:00Z" } ], "tagline": "The Future of Cloud Storage Starts Here", "contact_name": "Sarah Chen" } ``` **Important Notes** - The event starts in **draft** status (not yet live) - `event_type: "SIMPLE_EVENT"` is **immutable** - cannot be changed after creation. - `meeting_type: "WEBINAR"` supports up to 100,000 attendees (host/panelist video only). - Times must be in UTC format (`yyyy-MM-ddTHH:mm:ssZ`). **Save the `event_id`** - You will use it throughout the rest of the tutorial. --- ## Step 3: Retrieve the default Ticket Type Zoom Events automatically creates a "General Admission" ticket type when you create an event. Retrieve its ID. ### cURL ```shell curl -X GET "https://api.zoom.us/v2/zoom_events/events/kNqLPC6hSFiZ9NpgjA549w/ticket_types" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ### Python ```python import requests event_id = "kNqLPC6hSFiZ9NpgjA549w" url = f"https://api.zoom.us/v2/zoom_events/events/{event_id}/ticket_types" headers = { "Authorization": "Bearer YOUR_ACCESS_TOKEN" } response = requests.get(url, headers=headers) response.raise_for_status() # Check for HTTP errors ticket_types = response.json() # Get the first (default) ticket type ticket_type_id = ticket_types["ticket_types"][0]["ticket_type_id"] print(f"Ticket Type ID: {ticket_type_id}") print(f"Name: {ticket_types['ticket_types'][0]['name']}") ``` ### JavaScript (Node.js) ```javascript const axios = require("axios"); async function getTicketTypeId(eventId) { const url = `https://api.zoom.us/v2/zoom_events/events/${eventId}/ticket_types`; const headers = { Authorization: "Bearer YOUR_ACCESS_TOKEN", }; try { const response = await axios.get(url, { headers }); const ticketTypeId = response.data.ticket_types[0].ticket_type_id; console.log(`Ticket Type ID: ${ticketTypeId}`); console.log(`Name: ${response.data.ticket_types[0].name}`); return ticketTypeId; } catch (error) { console.error( "Failed to get ticket type:", error.response?.data || error.message, ); throw error; } } getTicketTypeId("kNqLPC6hSFiZ9NpgjA549w"); ``` ### Expected Response ```json { "total_records": 1, "ticket_types": [ { "ticket_type_id": "234kjhg23kl4jhlaksjdh3", "name": "General Admission", "currency": "USD", "free": true, "price": "0", "quantity": 50 } ] } ``` **Save the `ticket_type_id`** - You will use it when creating registration links and tickets. --- ## Step 4: Create a public registration link Create a registration link that anyone can use to sign up for the CloudSync Pro Launch. ### cURL ```shell curl -X POST "https://api.zoom.us/v2/zoom_events/events/kNqLPC6hSFiZ9NpgjA549w/access_links" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{ "name": "Public Registration", "type": "registration", "is_default": true, "authentication_method": "bypass_auth", "ticket_type_id": "234kjhg23kl4jhlaksjdh3", "security_at_join": { "email_authentication": false, "security_code_verification": false } }' ``` ### Python ```python import requests event_id = "kNqLPC6hSFiZ9NpgjA549w" ticket_type_id = "234kjhg23kl4jhlaksjdh3" url = f"https://api.zoom.us/v2/zoom_events/events/{event_id}/access_links" headers = { "Content-Type": "application/json", "Authorization": "Bearer YOUR_ACCESS_TOKEN" } link_data = { "name": "Public Registration", "type": "registration", "is_default": True, "authentication_method": "bypass_auth", "ticket_type_id": ticket_type_id, "security_at_join": { "email_authentication": False, "security_code_verification": False } } response = requests.post(url, headers=headers, json=link_data) response.raise_for_status() # Check for HTTP errors access_link = response.json() print(f"Registration link created") print(f"Link ID: {access_link['access_link_id']}") print(f"Type: {access_link['type']}") ``` ### JavaScript (Node.js) ```javascript const axios = require("axios"); async function createRegistrationLink(eventId, ticketTypeId) { const url = `https://api.zoom.us/v2/zoom_events/events/${eventId}/access_links`; const headers = { "Content-Type": "application/json", Authorization: "Bearer YOUR_ACCESS_TOKEN", }; const linkData = { name: "Public Registration", type: "registration", is_default: true, authentication_method: "bypass_auth", ticket_type_id: ticketTypeId, security_at_join: { email_authentication: false, security_code_verification: false, }, }; try { const response = await axios.post(url, linkData, { headers }); const accessLink = response.data; console.log("Registration link created"); console.log(`Link ID: ${accessLink.access_link_id}`); console.log(`Type: ${accessLink.type}`); return accessLink.access_link_id; } catch (error) { console.error( "Failed to create registration link:", error.response?.data || error.message, ); throw error; } } createRegistrationLink("kNqLPC6hSFiZ9NpgjA549w", "234kjhg23kl4jhlaksjdh3"); ``` ### Expected response ```json { "access_link_id": "xyz789abc456", "name": "Public Registration", "type": "registration", "is_default": true, "authentication_method": "bypass_auth", "ticket_type_id": "234kjhg23kl4jhlaksjdh3", "security_at_join": { "email_authentication": false, "security_code_verification": false } } ``` **What this does** - **`type: "registration"`** - Attendees must register before joining. - **`authentication_method: "bypass_auth"`** - No login required (public event). - **`is_default: true`** - This link is the primary registration path. - **`security_at_join.email_authentication: false`** - No email authentication required at join time. - **`security_at_join.security_code_verification: false`** - No security code required at join time. **Alternative authentication methods** - `zoom_account` - Require Zoom account sign-in - `zoom_account_otp` - Zoom account or email OTP - `corporate_idp` - Enterprise SSO (single sign-on) --- ## Step 5: Pre-register VIP attendees (optional) For the CloudSync Pro Launch, pre-register three VIP guests who should receive direct invitations. ### cURL ```shell curl -X POST "https://api.zoom.us/v2/zoom_events/events/kNqLPC6hSFiZ9NpgjA549w/tickets" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{ "tickets": [ { "email": "alex.rivera@techcorp.com", "first_name": "Alex", "last_name": "Rivera", "ticket_type_id": "234kjhg23kl4jhlaksjdh3", "send_notification": true, "fast_join": false }, { "email": "jordan.patel@innovate.io", "first_name": "Jordan", "last_name": "Patel", "ticket_type_id": "234kjhg23kl4jhlaksjdh3", "send_notification": true, "fast_join": false }, { "email": "taylor.kim@cloudsys.com", "first_name": "Taylor", "last_name": "Kim", "ticket_type_id": "234kjhg23kl4jhlaksjdh3", "send_notification": true, "fast_join": false } ] }' ``` ### Python ```python import requests event_id = "kNqLPC6hSFiZ9NpgjA549w" ticket_type_id = "234kjhg23kl4jhlaksjdh3" url = f"https://api.zoom.us/v2/zoom_events/events/{event_id}/tickets" headers = { "Content-Type": "application/json", "Authorization": "Bearer YOUR_ACCESS_TOKEN" } # VIP attendee list tickets_data = { "tickets": [ { "email": "alex.rivera@techcorp.com", "first_name": "Alex", "last_name": "Rivera", "ticket_type_id": ticket_type_id, "send_notification": True, "fast_join": False }, { "email": "jordan.patel@innovate.io", "first_name": "Jordan", "last_name": "Patel", "ticket_type_id": ticket_type_id, "send_notification": True, "fast_join": False }, { "email": "taylor.kim@cloudsys.com", "first_name": "Taylor", "last_name": "Kim", "ticket_type_id": ticket_type_id, "send_notification": True, "fast_join": False } ] } response = requests.post(url, headers=headers, json=tickets_data) response.raise_for_status() # Check for HTTP errors result = response.json() print(f"Pre-registered {len(result['tickets'])} VIP attendees") for ticket in result['tickets']: print(f" - {ticket['email']}: {ticket.get('event_join_link', 'N/A')}") ``` ### JavaScript (Node.js) ```javascript const axios = require("axios"); async function preRegisterVIPs(eventId, ticketTypeId) { const url = `https://api.zoom.us/v2/zoom_events/events/${eventId}/tickets`; const headers = { "Content-Type": "application/json", Authorization: "Bearer YOUR_ACCESS_TOKEN", }; const ticketsData = { tickets: [ { email: "alex.rivera@techcorp.com", first_name: "Alex", last_name: "Rivera", ticket_type_id: ticketTypeId, send_notification: true, fast_join: false, }, { email: "jordan.patel@innovate.io", first_name: "Jordan", last_name: "Patel", ticket_type_id: ticketTypeId, send_notification: true, fast_join: false, }, { email: "taylor.kim@cloudsys.com", first_name: "Taylor", last_name: "Kim", ticket_type_id: ticketTypeId, send_notification: true, fast_join: false, }, ], }; try { const response = await axios.post(url, ticketsData, { headers }); const result = response.data; console.log(`Pre-registered ${result.tickets.length} VIP attendees`); result.tickets.forEach((ticket) => { console.log( ` - ${ticket.email}: ${ticket.event_join_link || "N/A"}`, ); }); } catch (error) { console.error( "Failed to pre-register VIPs:", error.response?.data || error.message, ); throw error; } } preRegisterVIPs("kNqLPC6hSFiZ9NpgjA549w", "234kjhg23kl4jhlaksjdh3"); ``` ### Expected response ```json { "errors": [], "tickets": [ { "ticket_id": "ticket_abc123", "email": "alex.rivera@techcorp.com", "first_name": "Alex", "last_name": "Rivera", "event_join_link": "https://events.zoom.us/j/xyz123abc" }, { "ticket_id": "ticket_def456", "email": "jordan.patel@innovate.io", "first_name": "Jordan", "last_name": "Patel", "event_join_link": "https://events.zoom.us/j/xyz456def" }, { "ticket_id": "ticket_ghi789", "email": "taylor.kim@cloudsys.com", "first_name": "Taylor", "last_name": "Kim", "event_join_link": "https://events.zoom.us/j/xyz789ghi" } ] } ``` **What this does** - Creates tickets (registrations) for each VIP attendee. - **`send_notification: true`** - Each attendee receives confirmation email with join link. - **`fast_join: false`** - Attendees must verify email before joining (recommended for security). - Returns unique `event_join_link` for each attendee. ### Batch limits You can pre-register up to 30 attendees per API call. --- ## Step 6: Publish the event Now it is time to make your CloudSync Pro Launch event live. Publishing activates all registration links and makes the event discoverable. ### cURL ```shell curl -X POST "https://api.zoom.us/v2/zoom_events/events/kNqLPC6hSFiZ9NpgjA549w/event_actions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{ "operation": "publish" }' ``` ### Python ```python import requests event_id = "kNqLPC6hSFiZ9NpgjA549w" url = f"https://api.zoom.us/v2/zoom_events/events/{event_id}/event_actions" headers = { "Content-Type": "application/json", "Authorization": "Bearer YOUR_ACCESS_TOKEN" } publish_data = { "operation": "publish" } response = requests.post(url, headers=headers, json=publish_data) response.raise_for_status() # Check for HTTP errors result = response.json() print(f"Event published successfully") print(f"Status: {result['status']}") ``` ### JavaScript (Node.js) ```javascript const axios = require("axios"); async function publishEvent(eventId) { const url = `https://api.zoom.us/v2/zoom_events/events/${eventId}/event_actions`; const headers = { "Content-Type": "application/json", Authorization: "Bearer YOUR_ACCESS_TOKEN", }; const publishData = { operation: "publish", }; try { const response = await axios.post(url, publishData, { headers }); const result = response.data; console.log("Event published successfully"); console.log(`Status: ${result.status}`); } catch (error) { console.error( "Failed to publish event:", error.response?.data || error.message, ); throw error; } } publishEvent("kNqLPC6hSFiZ9NpgjA549w"); ``` ### Expected Response ```json { "status": "PUBLISHED", "event_id": "kNqLPC6hSFiZ9NpgjA549w" } ``` **Results when you publish:** - Event status changes from `draft` to `published`. - All registration links become active. - Event appears in your hub (if hub is public). - Confirmation emails are sent to pre-registered attendees. - The event is now accessible to registrants. **Important:** After publishing, certain fields become immutable (e.g., `meeting_type`, `event_type`). --- ## Step 7: Verify your event Confirm everything is set up correctly by retrieving the event details. ### cURL ```shell curl -X GET "https://api.zoom.us/v2/zoom_events/events/kNqLPC6hSFiZ9NpgjA549w" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ### Python ```python import requests event_id = "kNqLPC6hSFiZ9NpgjA549w" url = f"https://api.zoom.us/v2/zoom_events/events/{event_id}" headers = { "Authorization": "Bearer YOUR_ACCESS_TOKEN" } response = requests.get(url, headers=headers) response.raise_for_status() # Check for HTTP errors event = response.json() print("=" * 60) print("CloudSync Pro Launch Event Summary") print("=" * 60) print(f"Event Name: {event['name']}") print(f"Status: {event['status']}") print(f"Event Type: {event['event_type']}") print(f"Meeting Type: {event['meeting_type']}") print(f"Start Time: {event['calendar'][0]['start_time']}") print(f"Registration URL: {event['event_url']}") print(f"Tagline: {event.get('tagline', 'N/A')}") print("=" * 60) ``` ### JavaScript (Node.js) ```javascript const axios = require("axios"); async function verifyEvent(eventId) { const url = `https://api.zoom.us/v2/zoom_events/events/${eventId}`; const headers = { Authorization: "Bearer YOUR_ACCESS_TOKEN", }; try { const response = await axios.get(url, { headers }); const event = response.data; console.log("=".repeat(60)); console.log("CloudSync Pro Launch Event Summary"); console.log("=".repeat(60)); console.log(`Event Name: ${event.name}`); console.log(`Status: ${event.status}`); console.log(`Event Type: ${event.event_type}`); console.log(`Meeting Type: ${event.meeting_type}`); console.log(`Start Time: ${event.calendar[0].start_time}`); console.log(`Registration URL: ${event.event_url}`); console.log(`Tagline: ${event.tagline || "N/A"}`); console.log("=".repeat(60)); } catch (error) { console.error( "Failed to verify event:", error.response?.data || error.message, ); throw error; } } verifyEvent("kNqLPC6hSFiZ9NpgjA549w"); ``` ### Expected Output ```plaintext ============================================================ CloudSync Pro Launch Event Summary ============================================================ Event Name: CloudSync Pro Launch Status: PUBLISHED Event Type: SIMPLE_EVENT Meeting Type: WEBINAR Start Time: 2025-12-15T19:00:00Z Registration URL: https://zoom.us/events/abc123xyz Tagline: The Future of Cloud Storage Starts Here ============================================================ ``` **Verification checklist** - Status is `published` - `event_url` is accessible (share this link for registration) - Start/end times are correct - Event details match your specifications --- ## What you built Congratulations! You have successfully created a complete single-session virtual event. Here is what you accomplished: ### Event configuration - **Name:** CloudSync Pro Launch - **Type:** Single-session webinar (SIMPLE_EVENT) - **Capacity:** Up to 100,000 attendees - **Date:** December 15, 2025, 2:00 PM - 3:00 PM EST - **Status:** Published and live ### Registration setup - Public registration link (no login required) - Default "General Admission" ticket type - Pre-registered 3 VIP attendees with confirmation emails - Active registration URL ready to share ### Next steps Now that your event is live, you can: 1. **Share the registration link** - Use `event_url` from the event response - Embed on your website or share via email/social media 2. **Add branding (optional)** - Upload event logo and banner images - Customize colors and themes via the Zoom web portal 3. **Configure session settings** - Enable Q&A, polls, chat, reactions - Set up breakout rooms for networking - Configure recording settings 4. **Add speakers/panelists** - Use `POST /zoom_events/events/{eventId}/speakers` endpoint - Speakers appear on event page and in lobby 5. **Monitor registrations** - Use `GET /zoom_events/events/{eventId}/registrants` to view attendees - Export registration data for analysis 6. **Send reminder emails** - Zoom automatically sends reminders 1 day and 1 hour before - Customize email templates via the web portal --- ## Configuration options ### Meeting vs. Webinar Mode | Feature | MEETING | WEBINAR | | ------------------ | ---------------------- | ------------------------- | | **Max Capacity** | 1,000 attendees | 100,000 attendees | | **Video Sharing** | All participants | Host/panelists only | | **Screen Sharing** | All participants | Host/panelists only | | **Best For** | Workshops, roundtables | Presentations, broadcasts | **When to use meeting:** Interactive sessions where attendees need video/audio. **When to use webinar:** Large presentations where only hosts present. ### Access levels - **`PRIVATE_UNRESTRICTED`** - Anyone can register via link (no approval needed) - **`PRIVATE_RESTRICTED`** - Host must approve each registration ### Attendance types - **`VIRTUAL`** - Online-only event (default) - **`IN-PERSON`** - Physical venue only - **`HYBRID`** - Both virtual and in-person attendees For hybrid events, add `physical_location` field and enable check-in features. --- ## Troubleshooting ### Common errors #### Error 26501: Event not published **Problem:** Trying to create tickets before publishing event. **Solution:** Publish event first using Step 6, then create tickets. #### Error 261202: Ticket type not found **Problem:** Invalid `ticket_type_id` in request. **Solution:** Retrieve valid ticket type ID using Step 3. #### Error 260200: Event access denied **Problem:** Insufficient permissions or wrong hub. **Solution:** Verify API scopes and ensure you have host access to the hub. #### Error 26202: Event schedule cannot be more than 6 days **Problem:** Single-session events have a 6-day maximum duration. **Solution:** Reduce session length or use CONFERENCE type for multi-session events. #### Error 261203: Duplicate access link name **Problem:** An access link with this name already exists. **Solution:** Use a unique name for each registration link. --- ## API Reference quick links - [Create event](/docs/api/events/#tag/events/post/zoom_events/events) - [Create registration link](/docs/api/events/#tag/event-access/get/zoom_events/events/{eventId}/access_links) - [Pre-register attendees](/docs/api/events/#tag/tickets/post/zoom_events/events/{eventId}/tickets) - [Publish, duplicate or cancel](/docs/api/events/#tag/events/post/zoom_events/events/{eventId}/event_actions) - [List event hubs](/docs/api/events/#tag/hubs/get/zoom_events/hubs) - [List ticket types](/docs/api/events/#tag/ticket-types/get/zoom_events/events/{eventId}/ticket_types) --- ## Complete example code ### Python full workflow ```python import requests from datetime import datetime, timezone # Configuration BASE_URL = "https://api.zoom.us/v2/zoom_events" ACCESS_TOKEN = "YOUR_ACCESS_TOKEN" HEADERS = { "Content-Type": "application/json", "Authorization": f"Bearer {ACCESS_TOKEN}" } def create_product_launch_event(): # Step 1: Get Hub ID hubs_response = requests.get( f"{BASE_URL}/hubs", headers={"Authorization": f"Bearer {ACCESS_TOKEN}"}, params={"role_type": "host"} ) hubs_response.raise_for_status() # Check for HTTP errors hub_id = hubs_response.json()["hubs"][0]["hub_id"] print(f" Hub ID: {hub_id}") # Step 2: Create Event event_data = { "hub_id": hub_id, "name": "CloudSync Pro Launch", "": "Join us for the exclusive launch of CloudSync Pro... "timezone": "America/New_York", "event_type": "SIMPLE_EVENT", "access_level": "PRIVATE_UNRESTRICTED", "meeting_type": "WEBINAR", "attendance_type": "VIRTUAL", "tagline": "The Future of Cloud Storage Starts Here", "contact_name": "Sarah Chen", "calendar": [ { "start_time": "2025-12-15T19:00:00Z", "end_time": "2025-12-15T20:00:00Z" } ] } event_response = requests.post(f"{BASE_URL}/events", headers=HEADERS, json=event_data) event_response.raise_for_status() # Check for HTTP errors event_id = event_response.json()["event_id"] print(f" Event created: {event_id}") # Step 3: Get Ticket Type ticket_types_response = requests.get( f"{BASE_URL}/events/{event_id}/ticket_types", headers={"Authorization": f"Bearer {ACCESS_TOKEN}"} ) ticket_types_response.raise_for_status() # Check for HTTP errors ticket_type_id = ticket_types_response.json()["ticket_types"][0]["ticket_type_id"] print(f" Ticket Type ID: {ticket_type_id}") # Step 4: Create Registration Link link_data = { "name": "Public Registration", "type": "registration", "is_default": True, "authentication_method": "bypass_auth", "ticket_type_id": ticket_type_id, "security_at_join": { "email_authentication": False, "security_code_verification": False } } link_response = requests.post( f"{BASE_URL}/events/{event_id}/access_links", headers=HEADERS, json=link_data ) link_response.raise_for_status() # Check for HTTP errors print(f" Registration link created") # Step 5: Pre-register VIPs tickets_data = { "tickets": [ { "email": "alex.rivera@techcorp.com", "first_name": "Alex", "last_name": "Rivera", "ticket_type_id": ticket_type_id, "send_notification": True, "fast_join": False }, { "email": "jordan.patel@innovate.io", "first_name": "Jordan", "last_name": "Patel", "ticket_type_id": ticket_type_id, "send_notification": True, "fast_join": False } ] } tickets_response = requests.post( f"{BASE_URL}/events/{event_id}/tickets", headers=HEADERS, json=tickets_data ) tickets_response.raise_for_status() # Check for HTTP errors print(f" Pre-registered {len(tickets_response.json()['tickets'])} VIPs") # Step 6: Publish Event publish_response = requests.post( f"{BASE_URL}/events/{event_id}/event_actions", headers=HEADERS, json={"operation": "publish"} ) publish_response.raise_for_status() # Check for HTTP errors print(f" Event published") # Step 7: Get Event URL event_details_response = requests.get( f"{BASE_URL}/events/{event_id}", headers={"Authorization": f"Bearer {ACCESS_TOKEN}"} ) event_details_response.raise_for_status() # Check for HTTP errors event_details = event_details_response.json() print("\n" + "="*60) print("EVENT CREATED SUCCESSFULLY") print("="*60) print(f"Event Name: {event_details['name']}") print(f"Registration URL: {event_details['event_url']}") print(f"Start Time: {event_details['calendar'][0]['start_time']}") print("="*60) if __name__ == "__main__": create_product_launch_event() ``` --- ## Tutorial complete You now know how to create, configure, and publish a single-session virtual event using the Zoom Webinars Plus & Events API. **Questions or issues?** Check the [Troubleshooting](#troubleshooting) section or visit the [Zoom Developer Forum](https://devforum.zoom.us/).