Back to Weekly Business Review

Integration and API Spec

The reference during the build: every tool connection, auth scope, field mapping, and error-handling rule.

4 pagesPDF · Technical
FS-DOC-05Technical

Integration and API Spec

Weekly Business Review Automation

[YourCompany.com] · Management Department · Prepared by FullSpec · [Today's Date]

This document defines every integration point in the Weekly Business Review automation: authentication methods, required OAuth scopes, webhook and trigger configuration, field mappings between tools, credential store layout, and failure handling. It is written for the FullSpec build team and covers all six connected tools plus the orchestration layer. Nothing in this document requires action from the business owner; all configuration, credential storage, and testing is handled by FullSpec before any production credential is used.

01Tool inventory

Tool
Role in automation
Auth method
Min plan required
Used by agent(s)
Xero
Source of financial data: invoiced revenue, payments received, accounts receivable
OAuth 2.0 (authorization code flow)
Xero Starter or above (API access included on all paid plans)
Agent 1: Data Collection Agent
HubSpot
Source of CRM and pipeline data: open deals, pipeline value, closed deals, stage movement
Private App token (Bearer)
HubSpot Starter CRM or above (free tier lacks some API endpoints)
Agent 1: Data Collection Agent
Google Sheets
Master data store, target threshold reference tab, and input source for the narrative agent
OAuth 2.0 (service account or user delegation)
Google Workspace or free Google account (Sheets API enabled in GCP project)
Agent 1: Data Collection Agent; Agent 2: Review Narrative Agent
Google Slides
Weekly review presentation template: receives figures and narrative via named placeholders
OAuth 2.0 (same GCP project as Sheets)
Google Workspace or free Google account (Slides API enabled in GCP project)
Agent 3: Distribution Agent
Gmail
Sends the completed pack link and exception summary to the leadership distribution list
OAuth 2.0 (Gmail API, user account delegation)
Google Workspace or free Gmail account (Gmail API enabled in GCP project)
Agent 3: Distribution Agent
Slack
Posts formatted notification to the leadership channel with deck link and flagged metrics
Slack Bot Token (OAuth 2.0, Slack app installation)
Slack Free or above (incoming webhooks and chat:write available on all tiers)
Agent 3: Distribution Agent
Orchestration layer
Hosts all three agent workflows, manages the schedule trigger, routes data between tools, and holds the shared credential store
Internal (platform credential store); no external auth method
Automation platform subscription as scoped by FullSpec
All agents (shared infrastructure)
Before you connect anything: every integration must be validated against a sandbox or test account before production credentials are entered. Use Xero's demo company, HubSpot's sandbox portal, a non-production Google Sheet, and a private Slack channel for all initial connection tests. FullSpec will not write production credentials to the credential store until all sandbox tests pass.

02Per-tool integration detail

Xero

Used by Agent 1 (Data Collection Agent). Provides last week's invoiced revenue, payments received, and outstanding accounts receivable via the Xero Accounting API.

Auth method
OAuth 2.0 authorization code flow. The FullSpec automation platform acts as the OAuth client. Refresh tokens must be stored in the credential store and rotated automatically; Xero refresh tokens are valid for 60 days if unused.
Required scopes
openid profile email accounting.transactions.read accounting.reports.read offline_access
Trigger / webhook
No webhook required. The Data Collection Agent polls the Xero API on the scheduled trigger (Sunday 8 PM). No inbound webhook from Xero is needed for this process.
Required configuration
XERO_TENANT_ID stored in credential store (do not hardcode). OAuth client ID and client secret stored in credential store. Date range for the query must be calculated dynamically as ISO 8601: start = last Monday 00:00:00 UTC, end = last Sunday 23:59:59 UTC.
Key endpoints
GET /api.xro/2.0/Invoices?where=Status=="AUTHORISED"&DateFrom={start}&DateTo={end} | GET /api.xro/2.0/Reports/TrialBalance | GET /api.xro/2.0/Accounts?where=Type=="BANK"
Rate limits
Xero enforces 60 API calls per minute and a daily limit of 5,000 calls per organisation. This automation makes 3 to 5 calls per weekly run (52 runs/year = ~260 calls/year). Throttling is NOT required at current volume. A 429 response must trigger a 30-second back-off and one retry before raising an error.
Constraints
Xero OAuth tokens expire after 30 minutes (access token) and 60 days (refresh token). The platform must auto-refresh on every run. If the refresh token has expired, the workflow must halt and send an alert to support@gofullspec.com and the process owner rather than proceeding with stale data.
// Output fields written to credential / memory store
xero.weekly_invoiced_revenue   : float  // sum of AUTHORISED invoice amounts for the date range
xero.payments_received         : float  // sum of payments applied in the date range
xero.accounts_receivable       : float  // current outstanding AR balance
HubSpot

Used by Agent 1 (Data Collection Agent). Provides open deal count, total pipeline value, deals closed in the last seven days, and stage movement via the HubSpot CRM API v3.

Auth method
Private App access token (Bearer token). No OAuth redirect flow required. Token is long-lived but should be rotated every 90 days. Store as HUBSPOT_PRIVATE_APP_TOKEN in the credential store.
Required scopes
crm.objects.deals.read crm.objects.contacts.read sales-email-read crm.schemas.deals.read
Trigger / webhook
No inbound webhook. The Data Collection Agent queries HubSpot on the same scheduled trigger as Xero. No HubSpot workflow or subscription event is needed.
Required configuration
HUBSPOT_PIPELINE_ID stored in credential store (do not hardcode). Stage IDs for 'Closed Won' and 'Closed Lost' stored in credential store as HUBSPOT_STAGE_CLOSED_WON and HUBSPOT_STAGE_CLOSED_LOST. Date filter uses Unix epoch milliseconds.
Key endpoints
POST /crm/v3/objects/deals/search (filter by pipeline, close date range, and stage) | GET /crm/v3/pipelines/deals/{pipelineId}/stages
Rate limits
HubSpot enforces 100 requests per 10 seconds and 250,000 requests per day on Starter plans. This automation makes 2 to 4 calls per weekly run. Throttling is NOT required at current volume. On a 429 response, wait 10 seconds and retry once before raising an error.
Constraints
HubSpot deal search returns a maximum of 100 records per page. If the business has more than 100 open deals, the workflow must paginate using the 'after' cursor. Pipeline ID and stage IDs must never be hardcoded; changes to the HubSpot pipeline structure will silently break field mapping if IDs are embedded in code.
// Output fields written to credential / memory store
hubspot.open_deal_count         : int    // count of deals with stage != closed
hubspot.total_pipeline_value    : float  // sum of amount property on open deals
hubspot.deals_closed_this_week  : int    // deals moved to CLOSED_WON in date range
hubspot.deals_lost_this_week    : int    // deals moved to CLOSED_LOST in date range
hubspot.stage_movement_summary  : object // map of stage_id -> deal count delta
Google Sheets

Used by Agent 1 (write) and Agent 2 (read). The master Google Sheet holds weekly data rows, a target thresholds reference tab, and prior-week comparison data. Agent 2 reads from it to generate the narrative.

Auth method
OAuth 2.0 using a GCP service account with domain-wide delegation, or a user OAuth token with offline access. Service account is preferred for unattended Sunday-night execution. Store the service account JSON key as GOOGLE_SERVICE_ACCOUNT_KEY in the credential store.
Required scopes
https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive.file
Trigger / webhook
No inbound webhook. Agent 1 appends a row on schedule; Agent 2 reads the sheet after Agent 1 confirms a successful write. No Apps Script or Sheets trigger is needed.
Required configuration
GOOGLE_SHEET_ID stored in credential store. Tab names must match exactly: 'WeeklyData' (append target), 'Thresholds' (read target for Agent 2). Column header row must be row 1; data begins row 2. GOOGLE_SHEET_THRESHOLDS_RANGE stored as named range 'ThresholdTable' within the Thresholds tab.
Sheet structure (WeeklyData tab)
Columns: week_start_date | invoiced_revenue | payments_received | accounts_receivable | open_deal_count | pipeline_value | deals_closed | deals_lost | stage_movement_json | narrative_text | exception_flags | pack_sent_at
Sheet structure (Thresholds tab)
Columns: metric_key | target_value | tolerance_pct | direction (above/below) | owner_label
Rate limits
Google Sheets API allows 300 requests per minute per project and 60 requests per minute per user. This automation makes 2 to 4 read/write calls per run. Throttling is NOT required at current volume. On a 429 or 503, apply exponential back-off starting at 1 second, doubling up to 32 seconds, for a maximum of 5 retries.
Constraints
The spreadsheet must remain shared with the service account email address at Editor level. If the sheet is moved to a different Drive folder or the file ID changes, the GOOGLE_SHEET_ID credential must be updated. Column order in WeeklyData must not change without updating the field mapping in the orchestration layer.
// Agent 1 write: append row to WeeklyData
sheets.appendRow(GOOGLE_SHEET_ID, 'WeeklyData', [
  week_start_date, invoiced_revenue, payments_received,
  accounts_receivable, open_deal_count, pipeline_value,
  deals_closed, deals_lost, stage_movement_json
])

// Agent 2 read: last row of WeeklyData + full Thresholds tab
sheets.getLastRow(GOOGLE_SHEET_ID, 'WeeklyData')  -> current_week_data
sheets.getRange(GOOGLE_SHEET_ID, 'ThresholdTable') -> threshold_definitions
Google Slides

Used by Agent 3 (Distribution Agent). The standing weekly review deck is updated with new figures and the narrative text by replacing named text placeholders via the Slides API.

Auth method
OAuth 2.0 using the same GCP service account as Google Sheets. No separate credential is needed if both APIs are enabled in the same GCP project. Scope must include Slides write access.
Required scopes
https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/drive
Trigger / webhook
No inbound webhook. Agent 3 receives a handoff signal from Agent 2 confirming the narrative is written, then calls the Slides API to perform placeholder substitution.
Required configuration
GOOGLE_SLIDES_TEMPLATE_ID (the master template presentation ID) stored in credential store. GOOGLE_SLIDES_ARCHIVE_FOLDER_ID (Drive folder for dated copies) stored in credential store. Each weekly run must copy the template to a new file named 'Weekly Review YYYY-MM-DD' before writing data, to preserve the blank template.
Placeholder naming convention
All text placeholders in the deck must use double-brace syntax: {{invoiced_revenue}}, {{payments_received}}, {{accounts_receivable}}, {{open_deal_count}}, {{pipeline_value}}, {{deals_closed}}, {{deals_lost}}, {{week_start_date}}, {{narrative_text}}, {{exception_flags}}. Any slide redesign that removes or renames a placeholder will break substitution silently.
Rate limits
Google Slides API allows 300 requests per minute per project. This automation performs 1 batchUpdate call per run (10 to 15 replacements in a single request). Throttling is NOT required. On a 429 or 503, apply the same exponential back-off as Google Sheets.
Constraints
The Slides API does not support chart data updates via the REST API; chart data must be linked to the Google Sheet using the native 'link to spreadsheet' feature inside the deck, and a chart refresh must be triggered by the automation platform via a separate batchUpdate refreshSheetsChart request for each linked chart.
// Input from Agent 2 + Agent 1 data
slides_template_id   : string  // from credential store
replacement_map      : object  // { placeholder_key: value } for all {{}} tokens

// Step 1: copy template
drive.copyFile(GOOGLE_SLIDES_TEMPLATE_ID, 'Weekly Review ' + week_start_date, GOOGLE_SLIDES_ARCHIVE_FOLDER_ID)
  -> new_presentation_id : string

// Step 2: batch replace placeholders
slides.batchUpdate(new_presentation_id, replaceAllText(replacement_map))

// Output
slides.new_presentation_url : string  // shared link passed to Gmail and Slack agents
Integration and API SpecPage 1 of 3
FS-DOC-05Technical
Gmail

Used by Agent 3 (Distribution Agent). Sends the completed pack link and exception summary to the leadership distribution list using a standardised subject line and body template.

Auth method
OAuth 2.0 using the sending user's Google account (typically the operations manager's account or a dedicated automation@yourdomain.com address). Store refresh token as GMAIL_OAUTH_REFRESH_TOKEN and the sender address as GMAIL_SENDER_ADDRESS in the credential store.
Required scopes
https://www.googleapis.com/auth/gmail.send https://www.googleapis.com/auth/gmail.compose
Trigger / webhook
No inbound webhook. Gmail is the final send action in Agent 3. The workflow calls gmail.users.messages.send after the Slides update is confirmed.
Required configuration
GMAIL_SENDER_ADDRESS stored in credential store. GMAIL_DISTRIBUTION_LIST stored in credential store as a comma-separated string of recipient addresses (do not hardcode). Email subject template: 'Weekly Business Review | {week_start_date}'. Body must include the Google Slides link and the exception_flags summary. A plain-text fallback body must accompany every HTML body.
Rate limits
Gmail API allows 250 quota units per user per second; sending one message costs 100 units. This automation sends 1 email per weekly run (52/year). Throttling is NOT required. On a 429, wait 5 seconds and retry up to 3 times before raising an error and alerting support@gofullspec.com.
Constraints
If the sender account uses Google Workspace with a 'Send As' alias, the alias address must be verified in Gmail settings before the API can use it. The distribution list must be managed in the credential store, not in the workflow code, so recipients can be updated without a redeploy.
// Input
gmail.to      : GMAIL_DISTRIBUTION_LIST
gmail.from    : GMAIL_SENDER_ADDRESS
gmail.subject : 'Weekly Business Review | ' + week_start_date
gmail.body_html : rendered HTML including slides_new_presentation_url + exception_flags
gmail.body_text : plain-text fallback

// Output
gmail.message_id : string  // stored in WeeklyData row pack_sent_at field
Slack

Used by Agent 3 (Distribution Agent). Posts a formatted notification to the leadership channel confirming the pack is ready, with a direct link to the deck and a summary of any flagged metrics.

Auth method
Slack Bot Token (xoxb-) obtained via Slack app OAuth 2.0 installation. Install a dedicated Slack app to the workspace and store the bot token as SLACK_BOT_TOKEN in the credential store. Do not use a legacy webhook URL.
Required scopes
chat:write chat:write.public channels:read
Trigger / webhook
No inbound webhook to Slack. The automation platform calls the Slack Web API chat.postMessage endpoint after Gmail send is confirmed. SLACK_CHANNEL_ID for the leadership channel must be stored in the credential store (not the channel name, as names can change).
Required configuration
SLACK_BOT_TOKEN stored in credential store. SLACK_CHANNEL_ID stored in credential store. Message uses Block Kit JSON for structured formatting: a header block with the week date, a section block with the deck link, and a context block listing any exception_flags. If exception_flags is empty, the context block should read 'All metrics on target this week.'
Rate limits
Slack Web API Tier 3 methods (chat.postMessage) allow 50 requests per minute. This automation posts 1 message per weekly run. Throttling is NOT required. On a 429, honour the Retry-After header value before retrying once.
Constraints
The Slack app must be invited to the leadership channel before it can post. If the channel is archived or the bot is removed, the post will fail with a channel_not_found or not_in_channel error. These errors must trigger an alert rather than silently succeeding.
// Input
slack.channel   : SLACK_CHANNEL_ID
slack.token     : SLACK_BOT_TOKEN
slack.blocks    : BlockKit JSON array
  header.text   : 'Weekly Business Review | ' + week_start_date
  section.text  : 'Pack ready: ' + slides_new_presentation_url
  context.text  : exception_flags OR 'All metrics on target this week.'

// Output
slack.ts        : string  // message timestamp, logged for audit

03Field mappings between tools

The tables below define the exact field-level mappings at each agent handoff point. Source and destination field names are written in monospace to match the API response keys and the internal data model used by the orchestration layer.

Handoff 1: Xero API to Google Sheets (WeeklyData tab) via Agent 1

Source tool
Source field
Destination tool
Destination field
Xero
Invoices[].SubTotal (sum, AUTHORISED)
Google Sheets
invoiced_revenue
Xero
Payments[].Amount (sum, date range)
Google Sheets
payments_received
Xero
Accounts[].ReportValue where Type=RECEIVABLE
Google Sheets
accounts_receivable
Orchestration
schedule.trigger_date (ISO 8601 Monday of week)
Google Sheets
week_start_date

Handoff 2: HubSpot API to Google Sheets (WeeklyData tab) via Agent 1

Source tool
Source field
Destination tool
Destination field
HubSpot
deals[].id (count where stage != closed)
Google Sheets
open_deal_count
HubSpot
deals[].properties.amount (sum, open deals)
Google Sheets
pipeline_value
HubSpot
deals[].id (count where stage == CLOSED_WON, date range)
Google Sheets
deals_closed
HubSpot
deals[].id (count where stage == CLOSED_LOST, date range)
Google Sheets
deals_lost
HubSpot
deals[].properties.dealstage (grouped count delta per stage)
Google Sheets
stage_movement_json

Handoff 3: Google Sheets (WeeklyData + Thresholds) to Agent 2 narrative output, then back to Google Sheets

Source tool
Source field
Destination tool
Destination field
Google Sheets
WeeklyData[last_row].*
Agent 2 (internal)
current_week_data{}
Google Sheets
Thresholds[].metric_key
Agent 2 (internal)
threshold_definitions[].key
Google Sheets
Thresholds[].target_value
Agent 2 (internal)
threshold_definitions[].target
Google Sheets
Thresholds[].tolerance_pct
Agent 2 (internal)
threshold_definitions[].tolerance
Agent 2 (internal)
narrative_output.body_text
Google Sheets
narrative_text
Agent 2 (internal)
narrative_output.exception_list[]
Google Sheets
exception_flags

Handoff 4: Google Sheets + Agent 2 output to Google Slides via Agent 3

Source tool
Source field
Destination tool
Destination field
Google Sheets
WeeklyData.invoiced_revenue
Google Slides
{{invoiced_revenue}}
Google Sheets
WeeklyData.payments_received
Google Slides
{{payments_received}}
Google Sheets
WeeklyData.accounts_receivable
Google Slides
{{accounts_receivable}}
Google Sheets
WeeklyData.open_deal_count
Google Slides
{{open_deal_count}}
Google Sheets
WeeklyData.pipeline_value
Google Slides
{{pipeline_value}}
Google Sheets
WeeklyData.deals_closed
Google Slides
{{deals_closed}}
Google Sheets
WeeklyData.deals_lost
Google Slides
{{deals_lost}}
Google Sheets
WeeklyData.week_start_date
Google Slides
{{week_start_date}}
Agent 2 output
narrative_text
Google Slides
{{narrative_text}}
Agent 2 output
exception_flags
Google Slides
{{exception_flags}}

Handoff 5: Google Slides URL + exception flags to Gmail and Slack via Agent 3

Source tool
Source field
Destination tool
Destination field
Google Slides
new_presentation_url
Gmail
body_html (embedded link)
Google Slides
new_presentation_url
Slack
blocks[].section.text (deck link)
Agent 2 output
exception_flags
Gmail
body_html (exception summary section)
Agent 2 output
exception_flags
Slack
blocks[].context.text
Google Sheets
WeeklyData.week_start_date
Gmail
subject (date suffix)
Google Sheets
WeeklyData.week_start_date
Slack
blocks[].header.text (date suffix)
Integration and API SpecPage 2 of 3
FS-DOC-05Technical

04Build stack and orchestration

Orchestration layout
Three discrete workflows, one per agent. Each workflow is independently deployable and independently versioned. All three share a single credential store scoped to this process. No credentials are embedded in workflow logic; all sensitive values are referenced by key name only.
Workflow 1: Data Collection Agent trigger
Schedule trigger (cron). Fires every Sunday at 20:00 in the configured local timezone (stored as SCHEDULE_TIMEZONE in the credential store, default UTC). Poll interval: weekly. No inbound webhook. The trigger passes the ISO 8601 week_start_date as a runtime variable to downstream steps.
Workflow 2: Review Narrative Agent trigger
Event trigger (internal). Fires when Workflow 1 emits a 'row_written_success' completion event to the inter-workflow event bus. This is a push-based handoff, not a poll. If Workflow 1 does not emit the event within 10 minutes of its scheduled start, Workflow 2 must time out and log a 'upstream_timeout' error without executing.
Workflow 3: Distribution Agent trigger
Event trigger (internal). Fires when Workflow 2 emits a 'narrative_written_success' completion event. Same pattern as the Workflow 1 to 2 handoff. Timeout window: 5 minutes from expected Workflow 2 completion. Any critical_flag in exception_flags must pause Workflow 3 and emit a human_review_required notification to the process owner before the send step executes.
Webhook signature validation
No inbound webhooks are used by this automation. All triggers are either schedule-based or internal event-based. No HMAC signature validation is required for this build. If a future extension adds an inbound webhook (for example, a HubSpot workflow callback), HMAC-SHA256 validation must be implemented before deployment.
Inter-workflow event bus
The orchestration platform's native event/message passing mechanism is used for the Workflow 1 to 2 and Workflow 2 to 3 handoffs. Events carry a minimal payload: workflow_id, run_id, status, week_start_date, and sheet_row_index. No tool credentials or raw API responses are passed between workflows.
Credential store
All secrets are stored in the automation platform's encrypted credential store, referenced by the key names listed in the code block below. No credential value appears in workflow logic, logs, or error messages.
Credential store key manifest — do not log, print, or embed any of these values in workflow code or error output
// Credential store contents — Weekly Business Review automation
// All values are encrypted at rest. Reference by key name only in workflow logic.

// Xero
XERO_OAUTH_CLIENT_ID          : string   // Xero app client ID
XERO_OAUTH_CLIENT_SECRET      : string   // Xero app client secret
XERO_OAUTH_REFRESH_TOKEN      : string   // auto-rotated on each API call
XERO_TENANT_ID                : string   // Xero organisation tenant UUID

// HubSpot
HUBSPOT_PRIVATE_APP_TOKEN     : string   // Bearer token, rotate every 90 days
HUBSPOT_PIPELINE_ID           : string   // CRM pipeline UUID for deal queries
HUBSPOT_STAGE_CLOSED_WON      : string   // Stage ID for Closed Won
HUBSPOT_STAGE_CLOSED_LOST     : string   // Stage ID for Closed Lost

// Google (shared service account for Sheets, Slides, Gmail)
GOOGLE_SERVICE_ACCOUNT_KEY    : json     // full service account key JSON
GOOGLE_SHEET_ID               : string   // master Google Sheet file ID
GOOGLE_SLIDES_TEMPLATE_ID     : string   // blank template presentation ID
GOOGLE_SLIDES_ARCHIVE_FOLDER_ID : string // Drive folder ID for dated copies
GMAIL_SENDER_ADDRESS          : string   // sending address or alias
GMAIL_OAUTH_REFRESH_TOKEN     : string   // only if user OAuth used instead of SA
GMAIL_DISTRIBUTION_LIST       : string   // comma-separated recipient addresses

// Slack
SLACK_BOT_TOKEN               : string   // xoxb- prefixed bot token
SLACK_CHANNEL_ID              : string   // leadership channel ID (not name)

// Orchestration
SCHEDULE_TIMEZONE             : string   // e.g. 'America/New_York'
ALERT_EMAIL                   : string   // support@gofullspec.com (error alerts)
The service account key (GOOGLE_SERVICE_ACCOUNT_KEY) grants write access to the Google Sheet, the Slides template, and Gmail. Its permissions must be scoped to only the files listed above using GCP IAM and Google Drive share settings. It must never be granted project-level owner or editor permissions in GCP.

05Error handling and retry logic

Every integration point has a defined failure behaviour. Unhandled exceptions must never fail silently. All errors that halt a workflow must write a structured log entry and send an alert to ALERT_EMAIL (support@gofullspec.com) with the workflow name, run ID, step name, error code, and timestamp.

Integration
Scenario
Required behaviour
Xero OAuth
Access token expired at runtime
Auto-refresh using stored refresh token before the API call. If refresh succeeds, continue. If refresh fails (e.g. token revoked), halt workflow, log 'xero_token_refresh_failed', alert ALERT_EMAIL and process owner. Do not proceed with stale or empty data.
Xero API
HTTP 429 rate limit response
Wait 30 seconds. Retry once. If second attempt also returns 429, halt workflow and alert. Log 'xero_rate_limit_exceeded'. At 52 runs/year this should never occur; if it does, an upstream token-sharing issue is likely.
Xero API
HTTP 500 or 503 from Xero servers
Retry after 60 seconds. Retry a second time after 120 seconds. If both retries fail, halt workflow, log 'xero_api_unavailable', and alert ALERT_EMAIL. Do not write a partial row to Google Sheets.
HubSpot API
HTTP 401 invalid or expired private app token
Halt immediately. Log 'hubspot_auth_failed'. Alert ALERT_EMAIL and process owner with instructions to rotate the token in the credential store. Do not retry with an invalid token.
HubSpot API
Deal search returns zero records unexpectedly
Do not treat zero as a valid result without a check. If open_deal_count == 0 AND pipeline_value == 0, log a 'hubspot_zero_result_warning', write the row with a zero_flag = true marker, and include a warning in the exception_flags field so the narrative agent can surface it.
Google Sheets
HTTP 429 quota exhaustion on append
Apply exponential back-off: wait 1s, 2s, 4s, 8s, 16s, 32s before each retry (max 5 retries). If all retries fail, halt workflow and alert. Do not duplicate the row by retrying after partial success; check for an existing row with the same week_start_date before any retry append.
Google Sheets
Sheet ID not found or permission denied (403)
Halt immediately. Log 'sheets_access_denied'. Alert ALERT_EMAIL with the file ID and the service account email. Do not attempt to create a new sheet. The file ID or share settings must be corrected in the credential store before the next run.
Agent 2 (AI narrative)
AI model returns an empty or malformed narrative
Retry the generation call once with the same input. If the second attempt also fails validation (empty string or missing key sections), write a fallback narrative: 'Automated commentary unavailable for this week. Please review the data manually.' Write exception_flags from threshold comparison regardless. Do not block distribution.
Google Slides
Placeholder not found in deck (batchUpdate returns no replacements for a key)
Log 'slides_placeholder_missing' with the specific placeholder key name. Continue replacing remaining placeholders. After the run, include the missing placeholder list in the alert email. Do not abort distribution for a single missing placeholder, but alert so the template can be corrected.
Gmail
Send fails with HTTP 429 or daily quota exceeded
Retry after 5 seconds, then 30 seconds, up to 3 attempts. If all retries fail, log 'gmail_send_failed', halt the Gmail send step, alert ALERT_EMAIL, and still proceed with the Slack notification so the leadership channel is informed the pack is ready even if the email was not sent.
Slack
channel_not_found or not_in_channel error on chat.postMessage
Log 'slack_post_failed' with the channel ID. Alert ALERT_EMAIL immediately. Do not retry silently. This error requires a human to re-invite the bot to the channel. All prior steps (Sheets write, Slides update, Gmail send) are already complete and must be logged as successful regardless.
Orchestration (inter-workflow)
Workflow 1 does not emit 'row_written_success' within 10 minutes of schedule trigger
Workflow 2 times out and logs 'upstream_timeout_workflow1'. Alert ALERT_EMAIL with the run ID and scheduled start time. Workflow 2 and Workflow 3 must not execute. The process owner receives a single consolidated alert rather than three separate failure notifications.
All error alerts sent to support@gofullspec.com must include: workflow name, run ID, step name, ISO 8601 timestamp, HTTP status code or exception type, and a plain-English description of what failed. Never include credential values, raw API responses containing financial data, or personally identifiable information in alert payloads.
Integration and API SpecPage 3 of 3

More documents for this process

Every document generated for Weekly Business Review.

Launch Plan
Operations · Owner
View
ROI and Business Case
Finance · Owner
View
Process Runbook / SOP
Operations · Owner
View
Developer Handover Pack
Technical · Developer
View
Test and QA Plan
Quality · Developer
View