FS-DOC-05Technical
Integration and API Spec
Post-Meeting Recap and Follow-up
[YourCompany.com] · Sales Department · Prepared by FullSpec · [Today's Date]
This document is the authoritative technical reference for every integration point in the Post-Meeting Recap and Follow-up automation. It covers authentication methods, required OAuth scopes, webhook payload structures, field mappings between tools, credential-store contents, and error-handling behaviour. The FullSpec team uses this specification during build and as the baseline for QA. No integration detail should be hardcoded outside the credential store defined in Section 04.
01Tool inventory
Tool
Role in automation
Auth method
Min plan required
Used by agents
Google Calendar
Meeting-end trigger; attendee list source
OAuth 2.0 (service account or user delegation)
Google Workspace Business Starter
Agent 1 (Meeting Trigger Agent)
Zoom
Meeting-end webhook; recording availability signal
OAuth 2.0 server-to-server app
Zoom Pro
Agent 1 (Meeting Trigger Agent)
Fireflies.ai
Transcript and AI summary retrieval
API key (Bearer token)
Fireflies.ai Pro
Agents 1, 2 (Meeting Trigger Agent, Recap Drafting Agent)
Gmail
Recap email draft creation; rep notification delivery
OAuth 2.0 (user-scoped)
Google Workspace (any)
Agent 2 (Recap Drafting Agent)
Notion
Meeting summary block append to deal page
OAuth 2.0 (internal integration token)
Notion Plus or above
Agent 2 (Recap Drafting Agent)
HubSpot
Deal record update; follow-up task creation
OAuth 2.0 (private app token)
HubSpot Sales Hub Starter
Agent 3 (CRM and Task Sync Agent)
Slack
Rep nudge on draft ready; manager deal alert
OAuth 2.0 (bot token)
Slack Pro or Free (with bot support)
Agents 2, 3 (Recap Drafting Agent, CRM and Task Sync Agent)
Orchestration layer
Workflow sequencing, credential management, retry logic, error routing
Internal platform auth (credential store)
Determined at build
All agents
Before you connect anything: sandbox-test every connection using non-production credentials before pointing any integration at live data. Create a dedicated sandbox in HubSpot, use a test Notion workspace, and route Slack alerts to a private test channel. Fireflies.ai sandbox transcripts should use recordings that contain no real prospect data. Only promote credentials to the production credential store after all integration tests pass.
02Per-tool integration detail
Google Calendar
Provides meeting metadata (start time, end time, attendees, event title) used to detect qualifying sales meetings and populate the attendee list for the Gmail draft. The automation polls the Calendar API on a short interval or responds to a push notification channel registered via the watch endpoint.
Auth method
OAuth 2.0. Use a service account with domain-wide delegation if all reps share a Google Workspace domain, or individual user OAuth tokens if per-rep consent is required. Store the refresh token in the credential store; never store raw access tokens.
Required scopes
https://www.googleapis.com/auth/calendar.readonly
Webhook / trigger setup
Register a push notification channel via POST https://www.googleapis.com/calendar/v3/calendars/{calendarId}/events/watch with a channelId (UUID), type: 'web_hook', and the orchestration layer's inbound webhook URL as address. The channel expires after a maximum of 7 days; the automation must refresh the watch registration before expiry. Alternatively, poll GET /calendar/v3/calendars/{calendarId}/events?timeMin=now&singleEvents=true on a 5-minute interval if push channels are not available.
Required configuration
GCAL_CALENDAR_ID stored in credential store. Sales-meeting filter label or calendar tag (e.g. 'sales' keyword in event title or a specific calendar ID). Attendee domain exclusion list (internal domains to ignore) stored as GCAL_INTERNAL_DOMAINS in credential store.
Rate limits
Google Calendar API: 1,000,000 queries/day per project; 500 requests/100 seconds per user. At 40 meetings/month per rep, polling every 5 minutes generates approximately 8,640 requests/day per calendar, well within quota. No throttling required at current volume. Monitor quota usage in Google Cloud Console.
Constraints
Push notification channels require a verified HTTPS endpoint. Event updates (reschedule, cancellation) will re-trigger the watch; the automation must deduplicate by event ID and status=confirmed before proceeding.
// Output to Agent 1
calendar_event_id: string
event_title: string
end_time: ISO8601 datetime
attendees: [{ email: string, display_name: string }]
organizer_email: stringZoom
Provides a webhook signal when a meeting recording becomes available, supplementing the Google Calendar end-time trigger. The Meeting Trigger Agent uses this to confirm the call has fully ended and a recording exists before fetching the Fireflies.ai transcript.
Auth method
OAuth 2.0 server-to-server app (Zoom Marketplace). Generate a client_credentials grant using ZOOM_CLIENT_ID and ZOOM_CLIENT_SECRET stored in credential store. Access tokens expire after 1 hour; implement automatic token refresh.
Required scopes
recording:read:admin meeting:read:admin
Webhook / trigger setup
Subscribe to the recording.completed event type in the Zoom Event Subscriptions dashboard. Set the Event notification endpoint URL to the orchestration layer's inbound webhook URL. Enable webhook signature validation: Zoom signs payloads with a HMAC-SHA256 signature in the x-zm-signature header using the ZOOM_WEBHOOK_SECRET_TOKEN stored in credential store. Validate every inbound payload before processing.
Required configuration
ZOOM_CLIENT_ID, ZOOM_CLIENT_SECRET, ZOOM_WEBHOOK_SECRET_TOKEN, ZOOM_ACCOUNT_ID all stored in credential store. Meeting topic keyword filter (e.g. 'sales', 'discovery', 'demo') stored as ZOOM_MEETING_FILTER_KEYWORDS.
Rate limits
Zoom REST API: 30 requests/second per app. At 40 meetings/month this generates minimal API calls. No throttling required.
Constraints
Recording webhook fires only when cloud recording is enabled on the Zoom account. If a rep runs a meeting without cloud recording, the trigger falls back to the Google Calendar end-time only, and Fireflies.ai must supply the transcript independently.
// Webhook payload fields consumed by Agent 1
payload.object.id: string // Zoom meeting ID
payload.object.topic: string // meeting title for keyword filter
payload.object.start_time: ISO8601
payload.object.duration: integer // minutes
payload.object.host_email: string
payload.object.recording_files[].download_url: string
Fireflies.ai
The primary source of meeting transcripts and AI-generated summaries. The Meeting Trigger Agent queries the Fireflies.ai GraphQL API to retrieve the transcript matched to the meeting, and passes the full transcript text and summary to the Recap Drafting Agent.
Auth method
API key passed as Bearer token in the Authorization header. Store as FIREFLIES_API_KEY in credential store.
Required scopes
No OAuth scope model. The API key inherits the permissions of the Fireflies.ai user account it belongs to. The account must have the Fireflies bot added to the calendar or Zoom integration to auto-join meetings.
Webhook / trigger setup
Fireflies.ai provides a webhook (Integrations > Webhooks in the dashboard) that fires when a transcript is ready. Subscribe to the Transcription completed event and point it to the orchestration layer's inbound webhook URL. Use this as the preferred trigger over polling. Payload includes the meetingId, title, and organizer_email.
Required configuration
FIREFLIES_API_KEY in credential store. Fireflies bot must be added to the team's Google Calendar or Zoom account via the Fireflies.ai dashboard before any transcript is available. Fallback behaviour (calendar-only summary) configured as FIREFLIES_FALLBACK_ENABLED: true.
Rate limits
Fireflies.ai API: 100 requests/minute on Pro plan. At 40 meetings/month, peak load is negligible. No throttling required. If expanding to 10+ reps, monitor and implement a 1-second inter-request delay.
Constraints
Transcript availability can lag meeting end by 5 to 15 minutes depending on recording length. The automation must poll or wait for the webhook before proceeding. Meetings without a Fireflies bot participant produce no transcript; the fallback path must handle this gracefully.
// GraphQL query: GET transcript by meeting ID
query {
transcript(id: "<meetingId>") {
id
title
date
duration
organizer_email
participants
summary { overview action_items keywords }
sentences { index speaker_name text raw_words }
}
}Gmail
Receives the AI-generated recap email draft and saves it to the rep's Gmail Drafts folder, addressed to all meeting attendees. The Recap Drafting Agent also uses Gmail (via a Slack nudge) to prompt the rep to review the draft.
Auth method
OAuth 2.0 user-scoped. Each rep must individually authorise the integration. Store per-rep refresh tokens as GMAIL_REFRESH_TOKEN_{REP_ID} in credential store. Never store access tokens persistently.
Required scopes
https://www.googleapis.com/auth/gmail.compose https://www.googleapis.com/auth/gmail.readonly
Webhook / trigger setup
No inbound webhook required. The agent pushes a draft via POST https://gmail.googleapis.com/gmail/v1/users/me/drafts using the Gmail API. The rep receives the draft in their Drafts folder and a parallel Slack nudge.
Required configuration
GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET in credential store. Per-rep refresh tokens keyed by rep email address. GMAIL_RECAP_TEMPLATE_ID: the base template structure (greeting, sections, sign-off) stored as a plain-text template string in the credential store, not hardcoded in the workflow.
Rate limits
Gmail API: 250 quota units per user per second; creating a draft costs 10 units. At 40 meetings/month per rep, no throttling is required.
Constraints
The automation must never call gmail.send directly; it must use gmail.compose scope and create a draft only. Sending remains a manual step performed by the rep. Verify this constraint is enforced at the workflow level, not just by scope selection.
// Draft creation request body (Gmail API)
message.raw: base64url-encoded RFC 2822 message
// Headers included in raw message
To: <attendee_emails_joined_by_comma>
Subject: Recap: <event_title> - <event_date>
Content-Type: text/plain; charset=UTF-8
Integration and API SpecPage 1 of 3
FS-DOC-05Technical
Notion
Receives a structured meeting summary block from the Recap Drafting Agent and appends it to the deal's designated Notion page. Acts as the team knowledge base record for the meeting.
Auth method
OAuth 2.0 internal integration token. Create an integration in Notion Settings > Integrations, share the target database with the integration, and store the token as NOTION_INTEGRATION_TOKEN in credential store.
Required scopes
Notion internal integrations use capability checkboxes rather than OAuth scope strings. Enable: Read content, Update content, Insert content. Ensure the integration is shared with the Deals database and any page templates used.
Webhook / trigger setup
No inbound webhook. The Recap Drafting Agent pushes content via PATCH https://api.notion.com/v1/blocks/{page_id}/children to append a new block to the deal page.
Required configuration
NOTION_INTEGRATION_TOKEN in credential store. NOTION_DEALS_DATABASE_ID: the ID of the Notion database where deal pages live, stored in credential store. The deal page must be locatable by a unique deal identifier (HubSpot deal ID or meeting title) stored as a property on the Notion page. Page block template for meeting summaries stored as NOTION_SUMMARY_BLOCK_TEMPLATE in credential store.
Rate limits
Notion API: 3 requests/second average; bursts tolerated briefly. At 40 meetings/month the integration is well within limits. No throttling required.
Constraints
The integration token must have explicit page-level share permissions; workspace-level access is not granted by default. If the deal page does not yet exist in Notion, the agent must create it before appending, or log the failure and alert via Slack.
// Block appended to deal Notion page
{
type: 'toggle',
toggle: {
rich_text: [{ text: { content: '<event_title> | <event_date>' } }],
children: [
{ type: 'paragraph', paragraph: { rich_text: [{ text: { content: 'Attendees: <attendee_names>' } }] } },
{ type: 'paragraph', paragraph: { rich_text: [{ text: { content: 'Summary: <ai_summary_overview>' } }] } },
{ type: 'paragraph', paragraph: { rich_text: [{ text: { content: 'Action Items: <action_items_list>' } }] } }
]
}
}HubSpot
The CRM and Task Sync Agent writes meeting outcomes to the correct deal record, creates follow-up tasks from extracted action items, and optionally advances the deal stage when a stage keyword is detected in the transcript.
Auth method
Private app token (recommended over legacy API keys). Create a private app in HubSpot Settings > Integrations > Private Apps and store the token as HUBSPOT_PRIVATE_APP_TOKEN in credential store. Token does not expire but should be rotated on a quarterly schedule.
Required scopes
crm.objects.deals.read crm.objects.deals.write crm.objects.contacts.read crm.objects.tasks.write timeline oauth crm.schemas.deals.read
Webhook / trigger setup
No inbound webhook required for this integration. The agent pushes data via PATCH https://api.hubapi.com/crm/v3/objects/deals/{dealId} for deal updates and POST https://api.hubapi.com/crm/v3/objects/tasks for task creation. Deal matching uses the attendee email to look up the associated contact, then traverses the contact-to-deal association.
Required configuration
HUBSPOT_PRIVATE_APP_TOKEN in credential store. HUBSPOT_DEAL_STAGE_MAP: a JSON object mapping transcript keywords to HubSpot pipeline stage IDs (e.g. { 'send proposal': 'stage_id_proposal', 'book demo': 'stage_id_demo_scheduled' }), stored in credential store and editable without redeploying the workflow. HUBSPOT_PIPELINE_ID for the active sales pipeline. HUBSPOT_MEETING_OUTCOME_FIELD: the internal HubSpot field name for the meeting notes property (e.g. 'hs_meeting_body').
Rate limits
HubSpot API (Sales Hub Starter): 100 requests/10 seconds; 250,000 requests/day. At 40 meetings/month the daily call count is trivially low. No throttling required. If scaling beyond 20 reps, implement a 100ms inter-request delay as a precaution.
Constraints
Deal matching by attendee email will fail if the contact does not exist in HubSpot. The agent must handle the no-match case by logging the failure and sending a Slack alert to the rep with a direct link to create the contact manually. Stage advancement must only occur if the keyword confidence threshold (configurable, default 0.85) is met; never advance stage on ambiguous matches.
// Deal update PATCH body
properties: {
hs_meeting_body: '<ai_summary_overview>',
notes_last_updated: '<ISO8601_timestamp>',
dealstage: '<mapped_stage_id_or_unchanged>'
}
// Task creation POST body
properties: {
hs_task_subject: '<action_item_text>',
hs_task_status: 'NOT_STARTED',
hs_timestamp: '<due_date_ISO8601>',
hubspot_owner_id: '<rep_owner_id>'
}
associations: [{ to: { id: '<dealId>' }, types: [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 216 }] }]Slack
Used by two agents for two distinct purposes: the Recap Drafting Agent sends a nudge to the rep when the Gmail draft is ready, and the CRM and Task Sync Agent posts a formatted deal-update message to the sales channel for deals above the configured value threshold.
Auth method
OAuth 2.0 bot token. Install the Slack app to the workspace and store the bot token as SLACK_BOT_TOKEN in credential store. The bot must be invited to all channels it needs to post in.
Required scopes
chat:write chat:write.public users:read users:read.email channels:read im:write
Webhook / trigger setup
No inbound webhook required. The automation posts via POST https://slack.com/api/chat.postMessage using the bot token. For rep DMs, resolve the rep's Slack user ID from their email using users.lookupByEmail before posting. For channel posts, use the channel ID stored as SLACK_SALES_CHANNEL_ID in credential store.
Required configuration
SLACK_BOT_TOKEN in credential store. SLACK_SALES_CHANNEL_ID: the Slack channel ID for deal update posts (not the human-readable name). SLACK_DEAL_VALUE_THRESHOLD: the dollar amount above which the deal-update message is triggered, stored in credential store and editable without redeployment (default: $10,000). SLACK_NUDGE_MESSAGE_TEMPLATE and SLACK_DEAL_UPDATE_TEMPLATE as plain-text or Block Kit JSON templates stored in credential store.
Rate limits
Slack Web API: 1 request/second per method as a Tier 3 rate limit for chat.postMessage. At 40 meetings/month the post volume is approximately 1-2 messages per meeting (nudge plus optional deal alert), posing no throttling risk.
Constraints
The bot must be added to private channels manually by a workspace admin before it can post. users.lookupByEmail requires the users:read.email scope and will fail if the rep's Slack account email does not match their Google Workspace email; store a fallback SLACK_DEFAULT_REP_DM_CHANNEL as a safety net.
// Rep nudge DM payload
{
channel: '<rep_slack_user_id>',
text: 'Your recap draft for <event_title> is ready in Gmail. Review and send when ready.',
blocks: [ ... Block Kit blocks with link to Gmail drafts ... ]
}
// Deal update channel post payload
{
channel: SLACK_SALES_CHANNEL_ID,
text: 'Deal update: <deal_name> | <outcome_summary>',
blocks: [ ... Block Kit blocks with HubSpot deal link ... ]
}03Field mappings between tools
The following tables define every field mapping at each agent handoff point. Use exact field names as shown (monospace) when configuring the orchestration layer. Do not rename or alias fields at the platform level; transformation must happen inside the agent step.
Agent 1 handoff: Meeting Trigger Agent to Recap Drafting Agent
Source tool
Source field
Destination tool
Destination field
Google Calendar
`event.id`
Orchestration context
`context.calendar_event_id`
Google Calendar
`event.summary`
Fireflies.ai query / Gmail draft
`context.event_title`
Google Calendar
`event.end.dateTime`
Orchestration context
`context.meeting_end_time`
Google Calendar
`event.attendees[].email`
Gmail draft To field / Slack lookup
`context.attendee_emails[]`
Google Calendar
`event.attendees[].displayName`
Notion summary block
`context.attendee_names[]`
Google Calendar
`event.organizer.email`
HubSpot contact lookup
`context.organizer_email`
Zoom webhook
`payload.object.id`
Fireflies.ai query
`context.zoom_meeting_id`
Zoom webhook
`payload.object.host_email`
HubSpot contact lookup
`context.host_email`
Fireflies.ai
`transcript.id`
Orchestration context
`context.fireflies_transcript_id`
Fireflies.ai
`transcript.summary.overview`
Recap Drafting Agent input
`agent2.input.summary_overview`
Fireflies.ai
`transcript.summary.action_items`
Recap Drafting Agent input
`agent2.input.action_items[]`
Fireflies.ai
`transcript.sentences[]`
Recap Drafting Agent input
`agent2.input.full_transcript_text`
Fireflies.ai
`transcript.summary.keywords`
HubSpot stage-map lookup
`agent3.input.detected_keywords[]`
Agent 2 handoff: Recap Drafting Agent to CRM and Task Sync Agent
Source tool
Source field
Destination tool
Destination field
Recap Drafting Agent (AI output)
`draft.recap_body`
Gmail API
`message.raw` (encoded body)
Recap Drafting Agent (AI output)
`draft.subject_line`
Gmail API
`message.raw` (Subject header)
Recap Drafting Agent (AI output)
`draft.action_items[]`
HubSpot Tasks API
`properties.hs_task_subject`
Recap Drafting Agent (AI output)
`draft.action_item_due_dates[]`
HubSpot Tasks API
`properties.hs_timestamp`
Recap Drafting Agent (AI output)
`draft.summary_overview`
HubSpot Deals API
`properties.hs_meeting_body`
Recap Drafting Agent (AI output)
`draft.summary_overview`
Notion Blocks API
`toggle.children[1].paragraph.rich_text[0].text.content`
Recap Drafting Agent (AI output)
`draft.action_items_formatted`
Notion Blocks API
`toggle.children[2].paragraph.rich_text[0].text.content`
Orchestration context
`context.detected_keywords[]`
HubSpot Deals API
`properties.dealstage` (via HUBSPOT_DEAL_STAGE_MAP lookup)
Orchestration context
`context.event_title`
Gmail API
`message.raw` Subject prefix
Orchestration context
`context.attendee_emails[]`
Gmail API
`message.raw` To header
Orchestration context
`context.meeting_end_time`
HubSpot Deals API
`properties.notes_last_updated`
Orchestration context
`context.organizer_email`
Slack API
`users.lookupByEmail` query param
Orchestration context
`context.event_title`
Notion Blocks API
`toggle.rich_text[0].text.content` prefix
Orchestration context
`context.deal_value`
Slack conditional filter
`SLACK_DEAL_VALUE_THRESHOLD` comparison
Integration and API SpecPage 2 of 3
FS-DOC-05Technical
04Build stack and orchestration
Orchestration layout
Three discrete workflows, one per agent (Meeting Trigger Agent, Recap Drafting Agent, CRM and Task Sync Agent). Each workflow is independently deployable and testable. Agents communicate via a shared context object passed as a structured JSON payload between workflow executions. A single shared credential store is referenced by all three workflows; no credentials are duplicated across workflows.
Agent 1 trigger mechanism
Dual trigger: (1) Fireflies.ai webhook fires on transcript-ready event (preferred path). (2) Google Calendar push notification channel fires on event status change to 'ended' (fallback path if Fireflies webhook is delayed beyond 20 minutes). The orchestration layer deduplicates by calendar_event_id to prevent double execution. Webhook endpoint must validate the Fireflies.ai HMAC signature header on all inbound requests.
Agent 2 trigger mechanism
Webhook: Agent 1 completion emits an internal platform event containing the context payload. Agent 2 is triggered by this event. No polling. If the internal event is not received within 25 minutes of meeting end, a time-based fallback poll checks for any context payloads in the staging queue and processes them.
Agent 3 trigger mechanism
Webhook: Agent 2 completion emits an internal platform event when the Gmail draft has been created and the Notion block has been appended. Agent 3 is triggered by this event. Agent 3 does not wait for rep action on the Gmail draft; HubSpot and Slack updates fire immediately on draft creation, not on draft send.
Slack webhook signature validation
Not applicable for outbound-only Slack usage. If Slack interactive messages are added in future (e.g. approve/reject buttons), implement Slack request signature validation using SLACK_SIGNING_SECRET before processing any inbound Slack payload.
Zoom webhook signature validation
Validate x-zm-signature header on every inbound Zoom webhook using HMAC-SHA256 with ZOOM_WEBHOOK_SECRET_TOKEN. Reject and log any request that fails validation. Zoom also sends a validation challenge (event_type: endpoint.url_validation) on registration; the orchestration layer must respond with the encrypted plainToken before any live events are delivered.
Credential store type
The orchestration platform's native encrypted secrets store. All values referenced below are stored as named secrets and injected at runtime. No credentials appear in workflow logic, prompt templates, or log outputs.
Credential store: all entries injected at runtime; none hardcoded in workflow logic
// Credential store contents (all entries required before first run)
// Google Calendar
GCAL_CALENDAR_ID // target calendar ID (e.g. rep@yourcompany.com)
GCAL_CLIENT_ID // OAuth 2.0 client ID from Google Cloud Console
GCAL_CLIENT_SECRET // OAuth 2.0 client secret
GCAL_REFRESH_TOKEN // per-rep refresh token (replicate per rep as GCAL_REFRESH_TOKEN_{REP_ID})
GCAL_INTERNAL_DOMAINS // comma-separated list of internal email domains to filter out
// Zoom
ZOOM_CLIENT_ID // server-to-server OAuth app client ID
ZOOM_CLIENT_SECRET // server-to-server OAuth app client secret
ZOOM_ACCOUNT_ID // Zoom account ID for token endpoint
ZOOM_WEBHOOK_SECRET_TOKEN // secret token for HMAC webhook validation
ZOOM_MEETING_FILTER_KEYWORDS // comma-separated keywords: 'sales,discovery,demo,prospect'
// Fireflies.ai
FIREFLIES_API_KEY // Bearer token from Fireflies.ai dashboard
FIREFLIES_FALLBACK_ENABLED // boolean: 'true' enables calendar-only summary fallback
// Gmail
GMAIL_CLIENT_ID // OAuth 2.0 client ID
GMAIL_CLIENT_SECRET // OAuth 2.0 client secret
GMAIL_REFRESH_TOKEN_{REP_ID} // per-rep refresh token keyed by rep email slug
GMAIL_RECAP_TEMPLATE_ID // plain-text template string for recap email structure
// Notion
NOTION_INTEGRATION_TOKEN // internal integration secret from Notion dashboard
NOTION_DEALS_DATABASE_ID // ID of the Notion Deals database
NOTION_SUMMARY_BLOCK_TEMPLATE // JSON block template for meeting summary toggle block
// HubSpot
HUBSPOT_PRIVATE_APP_TOKEN // private app token from HubSpot settings
HUBSPOT_PIPELINE_ID // ID of the active sales pipeline
HUBSPOT_DEAL_STAGE_MAP // JSON: { 'keyword': 'stage_id', ... }
HUBSPOT_MEETING_OUTCOME_FIELD // internal property name e.g. 'hs_meeting_body'
HUBSPOT_STAGE_KEYWORD_CONFIDENCE // float threshold for stage advancement e.g. 0.85
// Slack
SLACK_BOT_TOKEN // xoxb- prefixed bot OAuth token
SLACK_SALES_CHANNEL_ID // channel ID (not name) for deal update posts
SLACK_DEAL_VALUE_THRESHOLD // integer dollar amount e.g. 10000
SLACK_NUDGE_MESSAGE_TEMPLATE // plain-text or Block Kit JSON for rep DM nudge
SLACK_DEAL_UPDATE_TEMPLATE // plain-text or Block Kit JSON for sales channel post
SLACK_DEFAULT_REP_DM_CHANNEL // fallback channel if users.lookupByEmail fails05Error handling and retry logic
Unhandled exceptions must never fail silently. Every error path must either retry with exponential backoff, route to a defined fallback, or post a structured alert to the designated error channel (SLACK_SALES_CHANNEL_ID with an error tag). Log the full error payload, the workflow step name, and the context.calendar_event_id for every failure to enable manual recovery.
Integration
Scenario
Required behaviour
Google Calendar
Push notification channel expires (7-day TTL reached)
The orchestration layer must re-register the watch channel at 6-day intervals using a scheduled maintenance workflow. If re-registration fails, fall back to 5-minute polling and alert via Slack error channel.
Google Calendar
Attendee list is empty or contains only internal domains
Skip the meeting and log a INFO-level entry. Do not trigger downstream agents. No alert required; this is expected for internal calls.
Zoom
Webhook validation challenge not responded to within 3 seconds
The orchestration layer must respond immediately to endpoint.url_validation events. If the response fails, Zoom will stop delivering events. Implement a dedicated lightweight handler with a 2-second timeout and alert the FullSpec team via support@gofullspec.com if validation repeatedly fails.
Zoom
recording.completed webhook not received within 20 minutes of calendar end time
Trigger the Fireflies.ai fallback path directly using the calendar_event_id and meeting title as matching keys. Log the timeout and continue processing without blocking.
Fireflies.ai
Transcript not yet ready when API is queried (status: processing)
Retry with exponential backoff: wait 2 min, then 4 min, then 8 min (max 3 retries). If still not ready after 14 minutes total, proceed with the AI-generated summary fields only and flag the Gmail draft with a note that the full transcript was unavailable.
Fireflies.ai
No transcript found for the meeting (bot was not present)
Activate calendar-only fallback path if FIREFLIES_FALLBACK_ENABLED is true. Generate a condensed recap using only calendar metadata (attendees, event title, duration). Flag the Gmail draft and Notion block as 'partial summary, transcript unavailable'. Post a Slack DM to the rep advising them to add the Fireflies bot to the meeting invite.
Gmail
OAuth refresh token expired or revoked for a rep
Halt draft creation for that rep. Post a Slack DM to the rep requesting they re-authorise the Gmail integration via the provided re-auth link. Log the failure with the rep's ID. Do not attempt to send via a different account.
Gmail
Draft creation API call returns 429 (quota exceeded)
Retry after 60 seconds (Gmail quota resets per minute). If three consecutive retries fail, log the error, store the draft content in the orchestration layer's temporary queue, and alert the rep via Slack with the draft text inline.
Notion
Target deal page not found in Notion database
Attempt to create a new Notion page in the Deals database using the event_title and organizer_email as the page title and owner property. If page creation also fails, log the raw summary block content to the orchestration error log and alert via Slack error channel with a manual-entry prompt.
HubSpot
No matching deal found for the organizer or attendee email
Do not create a new deal automatically. Log the failure with all attendee emails. Post a Slack DM to the rep with a pre-filled HubSpot new-deal link (deep link to the CRM with deal name pre-populated). Mark this meeting's context payload as requiring manual resolution.
HubSpot
Deal stage keyword detected but confidence below HUBSPOT_STAGE_KEYWORD_CONFIDENCE threshold
Do not advance the deal stage. Write the detected keyword and its confidence score to the deal notes field for rep review. No error alert required; log at INFO level.
HubSpot
Task creation API returns 500 or 503
Retry with exponential backoff: 30 seconds, 60 seconds, 120 seconds (max 3 retries). If all retries fail, post a Slack DM to the rep listing the action items that failed to create, formatted as a checklist they can add manually.
Slack
users.lookupByEmail returns no match for rep email
Fall back to posting the rep nudge to SLACK_DEFAULT_REP_DM_CHANNEL. Include the rep's email address in the message so a human can route it. Log the mismatch and flag it for credential store correction.
Slack
chat.postMessage returns 429 (rate limited)
Retry after the retry_after value supplied in the response header (typically 1 second). Queue all pending Slack messages and send sequentially with a 1.1-second inter-message delay. No alert required for transient rate limiting.
Orchestration layer
Any unhandled exception at any workflow step
Catch-all error handler must fire: log the full exception, the step name, the context.calendar_event_id, and a UTC timestamp to the platform error log. Post a structured error alert to SLACK_SALES_CHANNEL_ID tagged as ERROR. Never swallow exceptions silently. Contact support@gofullspec.com if the same error recurs across three consecutive meetings.
Integration and API SpecPage 3 of 3