Skip to content

Technical Reference

Advanced
SettingDescriptionDefault
Email:EnabledEnable/disable email monitoring-
Email:ProviderEmail provider (graph or imap)-
Email:MailboxBot’s email address-
Email:PollIntervalMinutesEmail mailbox check frequency~5 min
Email:RecurrenceHorizonDaysRecurring meeting expansion horizon7 days
JoinLeadTimeLead time before joining15 sec
DedupToleranceMeeting deduplication tolerance5 min
FallbackMeetingDurationAssumed duration if unknown4 hours
MaxWaitMinutesMaximum wait time in empty meetingConfigurable

The system processes up to 25 unread messages per polling cycle. For each message, invitation detection follows this priority order:

  1. ICS attachments in the email
  2. ICS embedded in MIME content
  3. Graph API EventMessage (when ICS is not found)
  • Meeting URL: patterns /l/meetup-join/ (legacy) and /meet/ (current)
  • Occurrence times
  • Meeting duration
  • Recurrence information (RRULE)
  • Meeting ID and Passcode (extracted from email body as fallback)

If no time is found, the meeting is scheduled immediately (with a 10-second delay).


Two possible paths to resolve the transcription destination:

The {{webhook:https://...}} pattern in the email body is detected and used directly. Does not require sender registration in Prodgy.

  1. Identify the sender

    • In forwarded emails: tries FromAddress first, falls back to SenderAddress
  2. Verify Prodgy registration

    • User not found → rejects
  3. Resolve the workspace

    • One product → uses automatically
    • Multiple workspaces → looks for [ProductName] notation in the meeting title
    • Notation not found with multiple workspaces → rejects
  4. Validate the agent

    • Agent not installed → rejects
    • No active version → rejects
    • No webhook trigger configured → rejects
  5. Return data

    • webhookUrl, userId, orgId, productId, agentBaseId

Before scheduling, the system applies these validations in sequence:

  1. Meeting already ended? — Checks if time + duration < now (fallback duration: 4 hours)
  2. Occurrence cancelled? — Checks the cancellation list (URL + timestamp, 5-minute tolerance)
  3. Already scheduled? — Same URL + time within 5-minute tolerance → merges the new target
  4. Bot already in active call? — Adds target to active call without new scheduling
  5. All validations pass — Creates ScheduledMeeting, persists to Redis, posts meeting_scheduled

After scheduling, the bot attempts to accept the calendar invitation via the email provider. Asynchronous execution — failures do not block scheduling.


  • Detects recurrence via RRULE (ICS) or PatternedRecurrence (Graph API)
  • Expands future occurrences within the configured horizon (RecurrenceHorizonDays)
  • Automatic re-expansion: every 12 hours, recalculates upcoming occurrences
  • Multi-user: merges targets when multiple users forward the same recurring invitation

AttemptWait
1st failure10 seconds
2nd failure30 seconds
3rd failure60 seconds

After 3 consecutive failures, the system posts a meeting_error event.

Before each attempt, the bot re-validates all targets. Users deactivated since scheduling are removed. If no valid targets remain, the join is cancelled.


AttemptWait
1st failure5 seconds
2nd failure15 seconds
3rd failure45 seconds
  • Each target is delivered independently — failure in one does not block the others
  • If 0 segments and 0 participants: webhook is not sent
  • Local backup saved to logs/transcripts/ before delivery
  • Backup file removed after successful delivery

The system persists all state to Redis:

DataDescription
Pending meetingsScheduled meetings awaiting join
Recurrence patternsRecurring meeting expansion rules
Cancelled occurrencesList of detected cancellations
Call-to-meeting mappingLink between call_id and session
  1. Loads cancelled occurrences
  2. Loads recurrence patterns
  3. Resets orphaned meetings (status joinedpending)
  4. Restores pending meetings and recreates timers
  5. Cleans up stale past meetings

GET /api/meeting-events

ParameterTypeDescription
organization_idrequiredFilter by organization
event_typeoptionalEvent type (e.g., meeting_joined)
statusoptionalStatus (completed, failed)
start_dateoptionalStart date (ISO 8601)
end_dateoptionalEnd date (ISO 8601)
limitoptionalResult limit (default: 200)
offsetoptionalOffset for pagination

Results ordered by creation date (most recent first).

GET /api/meetings/history/stream

  • Each new event triggers a notification via Server-Sent Events
  • No polling needed

Event recording uses fire-and-forget semantics: recording failures never block the meeting flow.