Your sub-account is connected. The next step is connecting a Zoom account, which is step 2 below.
The app is installed and the rest of your sub-accounts are ready to use. The ones that did not connect will be retried the first time a workflow runs in them, so this often resolves itself. If it does not, reinstall from the marketplace listing.
Nothing was connected, so there is nothing to undo. Start the install again from the marketplace listing — if it fails a second time, the app's install link may have expired.
Actions
All 12 actions, with every field they accept and every variable they return.
Each action's outputs are available to later steps as {{action_key.field}} — so Create Meeting's join link is {{zwa_create_meeting.joinUrl}}. The key under each heading is the one to use.
Blank is not the same as empty on any update action. The workflow builder sends every field on every run, including the ones you left alone, so a blank box means "leave this as it is" rather than "clear it". The exceptions are called out where they exist.
- Create Meeting — Schedule a Zoom meeting from a workflow.
- Get Meeting — Read a meeting's current state mid-workflow.
- Update Meeting — Change the time, topic or settings of a meeting already scheduled.
- Delete Meeting — Cancel a meeting and tell whoever registered.
- Add Registrant — Register a contact and get their personal join link.
- Get Registrant — Look up whether someone is registered, and whether they are approved.
- Update Registrant Status — Approve, deny or cancel a registration without leaving the workflow.
- Update Attendance — Mark the booking showed or no-show from what actually happened on the call.
- Create Webinar — Schedule a Zoom webinar from a workflow.
- Update Webinar — Reschedule or edit a webinar.
- Delete Webinar — Cancel a webinar and tell everyone registered.
- Add Webinar Registrant — Sign a contact up for a webinar and hand them their own link.
Create Meeting
Schedule a Zoom meeting from a workflow.
zwa_create_meeting
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
topic | text | yes | The meeting title. Merge fields are rendered before it reaches us. |
startTime | text | yes | Parsed leniently, so an appointment merge field can be dropped in as-is with no formatting step in between. |
duration | number | no · 30 | Minutes, up to 1440. |
timezone | text | no | An IANA name such as Europe/Lisbon. Zoom's account default when blank. |
agenda | text | no | The description Zoom shows on the meeting. |
password | text | no | Up to 10 characters. Zoom generates one when blank. |
hostVideo | toggle | no · on | Host camera on entry. |
participantVideo | toggle | no · on | Attendee cameras on entry. |
waitingRoom | toggle | no · on | Hold arrivals until the host admits them. |
enableRegistration | toggle | no · off | Turn registration on, which is what makes personal join links and attributable attendance possible. |
manualApproval | toggle | no · off | Hold registrations for screening instead of issuing links immediately. Ignored unless registration is on. |
appointmentId | text | no | Map {{appointment.id}}. Without it, attendance writeback has to find the booking by searching the contact's appointments and matching on start time. |
Returns
| Variable | Type | What it is |
|---|---|---|
meetingId | text | Zoom's numeric id, as a string — it exceeds what a number can hold exactly. |
joinUrl | text | The link to send a contact. |
startUrl | text | The host's start link. Whoever opens it starts the meeting as host. |
password | text | The meeting passcode. |
topic | text | As created. |
startTime | text | As created. |
duration | number | Minutes. |
timezone | text | As created. |
registrationEnabled | true/false | Whether registration is on. |
quotaRemaining | number | What Zoom's rate-limit header reported, or -1 when it said nothing. Not the 100-a-day create cap. |
deduplicated | true/false | True when a repeated request returned the meeting that already existed. |
Worth knowing
- startUrl is a credential, not a link. It embeds a token with a measured lifetime of two hours, and anyone holding it within that window takes the host seat — mute, remove, record, admit from the waiting room. Never send it to a contact. It sits next to joinUrl in the variable picker and the two names look interchangeable in a dropdown, which is exactly how the mistake gets made.
- startUrl is returned once, on creation, and never re-served. A retry that dedupes to an existing meeting gets an empty string rather than the credential again.
- quotaRemaining reads like the daily cap and is not. Zoom exposes no header for the real 100-a-day limit; this one reports a rate-limit category window and has been observed returning 399, a number the cap cannot produce.
Get Meeting
Read a meeting's current state mid-workflow.
zwa_get_meeting
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
meetingId | text | yes | A numeric id, not a join link. Spaces are stripped, so a value copied from Zoom's interface works. |
Returns
| Variable | Type | What it is |
|---|---|---|
meetingId | text | As requested. |
topic | text | Current title. |
agenda | text | Current description. |
startTime | text | Current start. |
duration | number | Minutes. |
timezone | text | Current timezone. |
joinUrl | text | The attendee link. |
password | text | The passcode. |
status | text | Zoom's own word: waiting or started. |
hostEmail | text | Which Zoom user hosts it. |
registrationEnabled | true/false | Whether registration is on. |
createdByThisApp | true/false | True when this app created it and holds the CRM correlation. |
Worth knowing
- There is no 'ended' status. Zoom reports a finished meeting as waiting again, indistinguishable from one that never ran, which is why attendance comes from the Meeting Ended trigger rather than from polling this.
Update Meeting
Change the time, topic or settings of a meeting already scheduled.
zwa_update_meeting
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
meetingId | text | yes | The meeting to change. |
topic | text | no | Left alone when blank. |
startTime | text | no | Parsed leniently, as on Create Meeting. |
duration | number | no | Minutes, up to 1440. |
timezone | text | no | Left alone when blank. |
agenda | text | no | Left alone when blank. |
password | text | no | Left alone when blank. |
hostVideo | toggle | no | Always applied. See the note below. |
participantVideo | toggle | no | Always applied. |
waitingRoom | toggle | no | Always applied. |
manualApproval | select | no · unchanged | Switch between automatic and manual approval, or leave approval as it is. Only reaches Zoom when registration is already on. |
Returns
| Variable | Type | What it is |
|---|---|---|
| … | Everything Get Meeting returns, describing the meeting after the change. | |
quotaRemaining | number | Same caveat as on Create Meeting. |
Worth knowing
- Blank means 'leave it alone', not 'clear it'. Zoom's update replaces what it receives, so sending an empty agenda because the workflow left the box empty would erase the agenda written at creation. Every text field here is skipped when blank.
- The three toggles are the exception, and it is worth reading twice. A toggle has no 'leave alone' state, so a step that only means to move the start time also applies whatever the video and waiting-room toggles happen to show. Set them to what the meeting should end up with, not to what you are changing.
- An update spends the same daily allowance as a creation. The cap is 100 create or update calls per Zoom user per day, so a workflow that reschedules on every reply can exhaust it without creating a single meeting.
Delete Meeting
Cancel a meeting and tell whoever registered.
zwa_delete_meeting
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
meetingId | text | yes | The meeting to cancel. |
notifyRegistrants | toggle | no · on | Email everyone registered that it is cancelled. |
notifyHost | toggle | no · off | Email the host too. Off, because the workflow's owner already knows. |
Returns
| Variable | Type | What it is |
|---|---|---|
meetingId | text | As requested. |
deleted | true/false | Whether the call removed it. |
alreadyGone | true/false | True when the meeting was not there to begin with. |
Worth knowing
- alreadyGone is not an error. A workflow that re-runs, or a host who cancelled in Zoom first, both land here, and 'the meeting is not there' is the outcome the step asked for either way.
- Notifying registrants defaults to on deliberately. Someone holding a personal join link for a meeting that no longer exists otherwise finds out by turning up to nothing.
Add Registrant
Register a contact and get their personal join link.
zwa_add_registrant A Licensed Zoom plan
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
meetingId | text | no | Usually left blank. When empty, the contact's current meeting is resolved from our own records. Supply it only to register someone for a meeting that is not their latest. |
email | text | yes | Zoom validates this. Map {{contact.email}}. |
firstName | text | no · empty | Zoom requires a first name, but a contact without one is an ordinary CRM record, so this is defaulted rather than rejected. |
lastName | text | no | Up to 64 characters. |
phone | text | no | Shown to the host on the registration. |
org | text | no | Company or organisation. |
jobTitle | text | no | Job title. |
city | text | no | City. |
state | text | no | State or region. |
country | text | no | Two-letter country code. Zoom rejects anything else. |
zip | text | no | Postal code. |
comments | text | no | Free text shown to the host alongside the registration. |
autoApprove | toggle | no · on | Approve immediately. On a manual-approval meeting a pending registrant gets no join link at all. |
Returns
| Variable | Type | What it is |
|---|---|---|
joinUrl | text | This person's personal link. The field the step exists to produce. |
registrantId | text | Zoom's id for the registration. |
meetingId | text | The meeting they were registered for. |
topic | text | The meeting title. |
startTime | text | When it starts. |
email | text | As registered. |
approved | true/false | False when the meeting is on manual approval and the link is still pending. |
alreadyRegistered | true/false | True when this email was already registered and the original link was returned. |
Worth knowing
- Do not map Create Meeting's meetingId into this step. GoHighLevel renders one marketplace action's output into another's input as an empty string, so the mapping silently produces nothing. Leaving the box blank is the supported path, and it resolves the contact's meeting from our own records.
- Registration is what turns attendance from a guess into a fact. Without it every attendee shares one link and Zoom reports them by whatever name they typed, so participantEmail arrives empty and a call cannot be tied to a person.
- A personal link belongs to one contact. Sending the same one to two people makes both of them the same attendee in every later report.
Get Registrant
Look up whether someone is registered, and whether they are approved.
zwa_get_registrant
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
meetingId | text | yes | The meeting to search. |
email | text | yes | Keyed on email, not on Zoom's registrant id — a workflow asking 'is this contact registered' has an email and nothing else. |
status | select | no · approved | approved, pending or denied. Search pending to find someone waiting on a manual-approval meeting. |
Returns
| Variable | Type | What it is |
|---|---|---|
found | true/false | Whether a registration was found. Branch on this. |
registrantId | text | Zoom's id, when found. |
email | text | As found. |
firstName | text | As registered. |
lastName | text | As registered. |
status | text | approved, pending or denied. Empty when not found. |
joinUrl | text | Their personal link. Empty while pending — Zoom issues it on approval. |
meetingId | text | As requested. |
Worth knowing
- Zoom's list defaults to approved registrations only, so leaving status alone reports a pending registrant as not registered — the exact case someone checking registration status usually cares about most.
- This also finds people who registered through Zoom's own page rather than through a workflow.
Update Registrant Status
Approve, deny or cancel a registration without leaving the workflow.
zwa_update_registrant_status
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
meetingId | text | yes | The meeting. |
email | text | yes | Who to act on. |
action | select | no · approve | approve issues the link; deny refuses a pending registration; cancel revokes an approved one and invalidates the link Zoom already emailed. |
Returns
| Variable | Type | What it is |
|---|---|---|
meetingId | text | As requested. |
email | text | As requested. |
action | text | What was asked for. |
applied | true/false | Whether it took effect. |
joinUrl | text | The link, after approving. Empty on deny and cancel, where there is deliberately no link to hand out. |
warning | text | Empty when it worked; a sentence otherwise. |
Worth knowing
- Approving is what issues the join link. A pending registrant has none until this runs, so a workflow that emails the link straight after Add Registrant on a manual-approval meeting sends an empty one.
Update Attendance
Mark the booking showed or no-show from what actually happened on the call.
zwa_update_attendance
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
meetingId | text | yes | Map {{zwa_meeting_ended.meetingId}}. The only required field — everything else is resolved from our own record of creating the meeting. |
status | select | no · auto | auto decides from attendance. The explicit values are new, confirmed, cancelled, showed, noshow and invalid. |
minimumMinutes | number | no · 1 | Minutes of attendance required to count as showed, in auto mode. Raise it to filter out the attendee who dials in, sees an empty room and leaves. |
appointmentId | text | no | Overrides appointment resolution. Rarely needed. |
showedTags | text | no | Comma-separated tags to add to the contact when they attended. |
noshowTags | text | no | Comma-separated tags to add when they did not. |
skipAppointmentUpdate | toggle | no · off | Apply tags only and leave the appointment alone, for customers driving their calendar from elsewhere. |
Returns
| Variable | Type | What it is |
|---|---|---|
status | text | The status written, or the one that would have been. |
attended | true/false | Whether anyone joined. |
attendedMinutes | number | The longest single attendance. |
attendeeCount | number | Distinct people who joined. |
actualMinutes | number | How long the meeting ran. |
appointmentId | text | The appointment written to, or empty when none was found. |
appointmentUpdated | true/false | Whether the calendar write happened. |
appointmentSource | text | How the appointment was found: provided, recorded, matched, or none. |
contactId | text | The contact. |
tagsAdded | text | Comma-separated tags actually applied. |
warning | text | Empty when everything worked; otherwise a sentence explaining what did not. |
Worth knowing
- minimumMinutes measures the longest single attendance, not the sum across people. Two people staying twenty minutes each is a twenty-minute meeting, not forty.
- This step returns success with a warning rather than failing. A workflow step that errors stops the whole run, and 'we could not find the appointment' should not stop the follow-up email going out. Branch on appointmentUpdated if you want to know.
- auto is the default because the honest answer is the one Zoom already gave. The explicit statuses exist for workflows with their own idea of an outcome — a discovery call that ran four minutes is a no-show to one agency and a win to another.
Create Webinar
Schedule a Zoom webinar from a workflow.
zwa_create_webinar A paid plan with the webinar add-on
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
topic | text | yes | The webinar title. |
startTime | text | yes | Parsed leniently, as on Create Meeting. |
duration | number | no · 60 | Minutes, up to 1440. Longer default than a meeting. |
timezone | text | no | Account default when blank. |
agenda | text | no | The description. |
password | text | no | Up to 10 characters. |
enableRegistration | toggle | no · on | The opposite default to a meeting. Registration is the point of the format and what makes attendance attributable. |
practiceSession | toggle | no · off | Attendees join muted and hidden. |
appointmentId | text | no | Map {{appointment.id}}, same as Create Meeting. |
Returns
| Variable | Type | What it is |
|---|---|---|
webinarId | text | A different id space from meetings — a webinar id is not a meeting id. |
joinUrl | text | The attendee link. |
startUrl | text | The host's start link. The same credential, with the same rules, as on Create Meeting. |
password | text | The passcode. |
topic | text | As created. |
startTime | text | As created. |
duration | number | Minutes. |
timezone | text | As created. |
registrationEnabled | true/false | Whether registration is on. |
quotaRemaining | number | Same caveat as on Create Meeting. |
deduplicated | true/false | True when a repeat returned the original. |
Worth knowing
- Deliberately narrower than Create Meeting. Panelists, polls, Q&A and practice sessions are real webinar features and are configured once in Zoom rather than re-specified on every workflow run.
- startUrl deserves a sharper warning here than on a meeting: a webinar has a registration page and an audience holding personal links, so whoever takes the host seat does it in front of everyone who signed up.
Update Webinar
Reschedule or edit a webinar.
zwa_update_webinar A paid plan with the webinar add-on
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
webinarId | text | yes | The webinar to change. |
topic | text | no | Left alone when blank. |
startTime | text | no | Left alone when blank. |
duration | number | no | Minutes, up to 1440. |
timezone | text | no | Left alone when blank. |
agenda | text | no | Left alone when blank. |
password | text | no | Left alone when blank. |
practiceSession | select | no · unchanged | A select rather than a toggle, so it has a genuine 'leave it alone'. |
Returns
| Variable | Type | What it is |
|---|---|---|
webinarId | text | As requested. |
topic | text | After the change. |
agenda | text | After the change. |
startTime | text | After the change. |
duration | number | Minutes. |
timezone | text | After the change. |
joinUrl | text | The attendee link. |
registrationUrl | text | The public sign-up page. |
password | text | The passcode. |
hostEmail | text | Which Zoom user hosts it. |
registrationEnabled | true/false | Whether registration is on. |
createdByThisApp | true/false | Whether this app created it. |
quotaRemaining | number | Same caveat as elsewhere. |
Worth knowing
- Worth more care than the meeting equivalent despite being nearly the same fields. Moving a meeting inconveniences one contact; moving a webinar affects everyone registered, and there may be hundreds of them.
Delete Webinar
Cancel a webinar and tell everyone registered.
zwa_delete_webinar A paid plan with the webinar add-on
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
webinarId | text | yes | The webinar to cancel. |
notifyRegistrants | toggle | no · on | Email everyone registered. |
Returns
| Variable | Type | What it is |
|---|---|---|
webinarId | text | As requested. |
deleted | true/false | Whether the call removed it. |
alreadyGone | true/false | True when it was not there to begin with. |
Add Webinar Registrant
Sign a contact up for a webinar and hand them their own link.
zwa_add_webinar_registrant A paid plan with the webinar add-on
Fields
| Field | Type | Required | What it does |
|---|---|---|---|
webinarId | text | yes | Required here, unlike on Add Registrant — webinars and meetings share no id space. |
email | text | yes | Zoom validates this. Map {{contact.email}}. |
firstName | text | no · empty | Zoom requires a first name, but a contact without one is an ordinary CRM record, so this is defaulted rather than rejected. |
lastName | text | no | Up to 64 characters. |
phone | text | no | Shown to the host on the registration. |
org | text | no | Company or organisation. |
jobTitle | text | no | Job title. |
city | text | no | City. |
state | text | no | State or region. |
country | text | no | Two-letter country code. Zoom rejects anything else. |
zip | text | no | Postal code. |
comments | text | no | Free text shown to the host alongside the registration. |
Returns
| Variable | Type | What it is |
|---|---|---|
joinUrl | text | This person's personal link. |
registrantId | text | Zoom's id for the registration. |
webinarId | text | As requested. |
topic | text | The webinar title. |
startTime | text | When it starts. |
email | text | As registered. |
alreadyRegistered | true/false | True when this email was already signed up. |
Worth knowing
- This mirrors Add Registrant field for field against the webinar endpoint. They are two actions rather than one with a toggle, so a wrong id fails visibly in the workflow rather than quietly inside ours.