Meetings
Create Zoom and Webex meetings with calendar events, hosted through a per-user grant or a server app.
Set onlineMeetingService on a calendar event and Workwae creates a Zoom or Webex meeting for it. Connect a host first: each user's own grant, or one server app for the organization.
Meetings with calendar events
With onlineMeetingService (zoom or webex) on a calendar event, Workwae:
- creates the meeting and writes its join link into the event's
onlineMeetingUrlon Google, Microsoft 365 and CalDAV; - moves the meeting when the event moves;
- deletes it when the event is deleted or cancelled.
Meetings need the meetings module in the tenant's plan; without it the field answers 403 plan_module_unavailable.
curl -X POST "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/calendar-events" \
-H "Authorization: Bearer $WORKWAE_API_KEY" \
-H "content-type: application/json" \
-d '{
"calendarId": "'"$CALENDAR_ID"'",
"subject": "Customer onboarding",
"start": { "dateTime": "2026-11-03T15:00:00", "timeZone": "America/Chicago" },
"end": { "dateTime": "2026-11-03T15:45:00", "timeZone": "America/Chicago" },
"recurrence": ["RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=8"],
"onlineMeetingService": "zoom"
}'- A series gets a recurring meeting translated from its rule. A rule the service cannot repeat by is refused with
meeting_recurrence_unsupportedbefore anything is created. - A new subject, start, end or rule moves the meeting.
- Changing one occurrence leaves the service's series alone; its join link works for every occurrence.
- Only one of
onlineMeeting,onlineMeetingUrlandonlineMeetingServicemay be set (multiple_meeting_options).
Workwae only creates, updates and deletes meetings and looks up the host. It never reads recordings, chat, transcripts or participant lists.
Who hosts the meeting
For each event, Workwae picks the host in this order:
- The account's own grant at the service.
- The tenant's server app for that service.
- Otherwise it refuses with
meeting_service_not_connected.
A grant that needs reconnecting is not passed over for the app.
| Option | How it works |
|---|---|
| User grant, platform app | The account's user signs in to Zoom or Webex through Workwae's app on a hosted page. The meeting is hosted by that service user. |
| User grant, your own app | The same, through your Zoom OAuth app (zoom_oauth) or Webex integration (webex_oauth). |
| Server app | A Zoom Server-to-Server OAuth app (zoom_s2s) or a Webex Service App (webex_service_app) hosts for every mailbox in the organization, as the service user with the mailbox's address. No per-user sign-in. |
- A server app is used only where the provider vouches for the mailbox's address: Gmail, Microsoft 365, and IMAP accounts signed in with Google or Microsoft OAuth.
- A password IMAP account needs its user's own grant.
- A mailbox with no matching user at the service is refused with
meeting_host_missing.
Per-user grants
Create a connect session
Pass meetingAppId to sign in through your own app instead of Workwae's.
curl -X POST "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/meeting-connect-sessions" \
-H "Authorization: Bearer $WORKWAE_API_KEY" \
-H "content-type: application/json" \
-d '{ "service": "webex", "redirectUri": "https://app.example.com/settings/meetings", "state": "user-42" }'Send the user to url
They see a page naming your tenant, the service and the account, and sign in at Zoom or Webex. The sign-in must finish in the same browser, and one link connects once.
Handle the return
The user comes back to your redirectUri with the outcome and your state, for example ?status=success&service=webex&state=user-42. Connecting again replaces the account's grant.
List an account's grants, or disconnect one. Disconnecting deletes the grant; existing meetings stay.
curl "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/meeting-connections" \
-H "Authorization: Bearer $WORKWAE_API_KEY"
curl -X DELETE "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/meeting-connections/webex" \
-H "Authorization: Bearer $WORKWAE_API_KEY"Server apps
Register one server app per service per tenant; a second answers meeting_app_exists.
- A new app starts unverified.
POST /v1/meeting-apps/{appId}/testrequests a token the way meetings will, optionally looks up a host by address, and marks the appactiveorfailing.- Deleting a server app leaves the meetings it created at the service.
curl -X POST "https://api.workwae.com/v1/meeting-apps" \
-H "Authorization: Bearer $WORKWAE_API_KEY" \
-H "content-type: application/json" \
-d '{
"kind": "zoom_s2s",
"name": "Acme Zoom",
"accountId": "'"$ZOOM_ACCOUNT_ID"'",
"clientId": "'"$ZOOM_CLIENT_ID"'",
"clientSecret": "'"$ZOOM_CLIENT_SECRET"'"
}'
curl -X POST "https://api.workwae.com/v1/meeting-apps/$APP_ID/test" \
-H "Authorization: Bearer $WORKWAE_API_KEY" \
-H "content-type: application/json" \
-d '{ "user": "priya@acme.com" }'Errors and reauthorization
A 401 or 403 from the service is retried once with a fresh token. Refused again, the grant is marked reauth_required and meeting_connection.reauth_required is sent with the service, host email and reason. Mail and calendar sync never use meeting grants, so they keep running.
| Reason | Meaning |
|---|---|
meeting_service_not_connected | No grant at the service and no server app the account may use. |
meeting_service_reauth_required | The account's grant or the tenant's server app was refused. |
meeting_host_missing | The server app has no user with the mailbox's address. |
meeting_recurrence_unsupported | The service cannot repeat a meeting by the event's rule. |
meeting_deleted | The meeting is gone at the service when Workwae tries to move it. |
meeting_service_rejected, meeting_service_unavailable | The service refused the meeting, or could not be reached. |
Send the user to reconnect on the first two:
import { isApiError } from "@workwae/sdk";
try {
await workwae.calendarEvents.create({ ...booking, onlineMeetingService: "zoom" });
} catch (error) {
if (
isApiError(error, "meeting_service_not_connected") ||
isApiError(error, "meeting_service_reauth_required")
) {
return askUserToConnect(booking.accountId, "zoom");
}
throw error;
}Meetings outlive grants
Disconnecting a grant or removing the app leaves existing meetings and their links on the events.
Every route is in the Meeting connections and Meeting apps references.