Back to Cash Flow Forecasting

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

Cash Flow Forecasting Automation

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

This document defines every integration point in the Cash Flow Forecasting automation: the tools connected, the exact OAuth scopes and credentials required, field mappings between agent handoffs, orchestration layout, and error handling behaviour for every failure scenario. It is written for the FullSpec build team and assumes familiarity with REST APIs, OAuth 2.0, and webhook validation patterns. The owner-facing SOP and Runbook cover what the finance lead does at runtime. This document covers what the automation platform does beneath the surface.

01Tool inventory

Tool
Role in automation
Auth method
Min plan required
Used by agent(s)
Xero
Source: bank transactions, AR ageing, upcoming bills
OAuth 2.0 (PKCE flow)
Starter or above (API access on all paid plans)
Agent 1 (Data Collection)
Stripe
Source: pending payout schedule and amounts
API key (restricted key, read-only)
Any paid or free account with Payouts enabled
Agent 1 (Data Collection)
Google Sheets
Forecast model write target; approval trigger source
OAuth 2.0 (service account JSON)
Google Workspace Business Starter or free with Drive API enabled
Agent 2 (Categorisation), Agent 3 (Distribution)
Gmail
Outbound: forecast PDF delivery to stakeholder list
OAuth 2.0 (delegated, send-as scope)
Google Workspace (same tenant as Sheets)
Agent 3 (Distribution)
Slack
Outbound: formatted cash summary to finance channel
OAuth 2.0 (Bot Token, Slack app)
Free tier or above (incoming webhooks available on all plans)
Agent 3 (Distribution)
Automation platform
Orchestration layer: schedules, credential store, retry engine, workflow routing
Internal (platform native)
Plan supporting cron scheduling, webhook listeners, and secure credential vault
All agents
Before you connect anything: provision sandbox or test credentials for every tool in this inventory and validate each connection end-to-end before any production credentials are entered. Xero provides a demo company environment. Stripe sandbox mode is available on all accounts. Use a non-production Google Sheet and a private Slack channel for initial testing. Production credentials must only be stored in the credential vault, never in workflow configuration fields.

02Per-tool integration detail

Xero

Used by Agent 1 (Data Collection Agent) to retrieve cleared bank transactions, AR ageing buckets, and upcoming bills payable within the next 8 weeks. All calls are made server-side on a Monday schedule trigger. Pagination must be handled; Xero returns a maximum of 100 records per page for transaction endpoints.

Auth method
OAuth 2.0 with PKCE. Register a Xero app at developer.xero.com. Redirect URI must point to the automation platform's OAuth callback endpoint. Refresh token rotation is automatic; store both access_token and refresh_token in the credential vault and update both on each token refresh response.
Required scopes
openid profile email accounting.transactions.read accounting.reports.read accounting.settings.read offline_access
Webhook / trigger setup
No inbound webhook from Xero is used. The Data Collection Agent initiates all calls on the Monday cron schedule. Xero does offer event subscriptions but they are not required for this pattern.
Required configuration
Store in credential vault: XERO_CLIENT_ID, XERO_CLIENT_SECRET, XERO_TENANT_ID, XERO_ACCESS_TOKEN, XERO_REFRESH_TOKEN. XERO_TENANT_ID is the organisation UUID returned from the /connections endpoint after the initial OAuth handshake. Never hardcode tenant ID in the workflow definition.
Endpoints used
GET /api.xero.com/api.xro/2.0/BankTransactions?where=Status%3D%22AUTHORISED%22&ModifiedAfter={iso_date} | GET /api.xero.com/api.xro/2.0/Reports/AgedReceivablesByContact | GET /api.xero.com/api.xro/2.0/Invoices?where=Type%3D%22ACCPAY%22%26Status%3D%22AUTHORISED%22&DueDateFrom={today}&DueDateTo={8_weeks}
Rate limits
60 calls/minute per app per tenant (minute window); 5,000 calls/day per tenant. At current volume (3 endpoints, 1 run/week, max 5 paginated pages per endpoint) peak usage is approximately 15 calls per run. No throttling logic is required at current volume, but implement exponential backoff on HTTP 429 responses as a precaution.
Constraints
Access tokens expire after 30 minutes. The refresh flow must be triggered proactively before expiry if a run is expected to exceed 30 minutes. Xero does not support bulk transaction export via API for more than 100 records per page; pagination loop is mandatory. Multi-entity (multi-tenant) setups require a separate XERO_TENANT_ID credential per entity and a separate workflow execution per tenant.
// Input
XERO_TENANT_ID: string (UUID from credential vault)
date_from: ISO-8601 string (Monday minus 7 days)
date_to: ISO-8601 string (today, Monday 08:00 local)
// Output
xero_transactions: Transaction[]  // cleared bank transactions
xero_ar_ageing: ARBucket[]        // overdue buckets: current, 1-30, 31-60, 61-90, 90+
xero_bills_payable: Bill[]        // upcoming bills with DueDate and AmountDue
Stripe

Used by Agent 1 (Data Collection Agent) to retrieve the payout schedule for the next 8 weeks. Only read access is required. The restricted API key model is preferred over a full secret key.

Auth method
Restricted API key (read-only). Create a restricted key in the Stripe Dashboard under Developers > API keys. Grant read permission on Payouts only. Store the key as STRIPE_RESTRICTED_KEY in the credential vault. No OAuth flow is required.
Required scopes
Restricted key permissions: payouts:read. No additional Stripe Connect scopes are needed unless processing on behalf of a connected account.
Webhook / trigger setup
No inbound Stripe webhook is used. The Data Collection Agent polls the Payouts list endpoint on the Monday schedule. If future requirements include real-time payout status updates, register a webhook for payout.paid and payout.failed events, validating the Stripe-Signature header using STRIPE_WEBHOOK_SECRET stored in the credential vault.
Required configuration
Store in credential vault: STRIPE_RESTRICTED_KEY. Optionally store STRIPE_WEBHOOK_SECRET if webhook listener is added later. The Stripe account ID does not need to be stored separately; it is implicit in the API key.
Endpoints used
GET /v1/payouts?status=pending&limit=100&arrival_date[lte]={8_weeks_unix_timestamp}
Rate limits
100 read requests/second in live mode. At current volume (1 API call per weekly run) no throttling is needed. Implement retry with 1-second delay on HTTP 429 as a baseline precaution.
Constraints
The Stripe Payouts endpoint returns payouts for the connected bank account only. If the business runs multiple Stripe accounts, a separate STRIPE_RESTRICTED_KEY is required per account and results must be merged in the data payload before handoff to Agent 2. Payout arrival dates are returned as Unix timestamps; convert to ISO-8601 before storing in the data payload.
// Input
STRIPE_RESTRICTED_KEY: string (from credential vault)
arrival_date_lte: Unix timestamp (today + 56 days)
// Output
stripe_payouts: Payout[]  // fields: id, amount, currency, arrival_date (ISO-8601), status
Google Sheets

Used by Agent 2 (Categorisation Agent) to write categorised transaction data into the master forecast sheet, and by Agent 3 (Distribution Agent) to poll the approval cell and trigger downstream delivery. A service account is used to avoid dependency on an individual user's credentials.

Auth method
OAuth 2.0 via Google service account. Create a service account in Google Cloud Console, download the JSON key file, and store it as GOOGLE_SERVICE_ACCOUNT_JSON in the credential vault. Share the master Google Sheet with the service account email address (editor permission for Agent 2 writes; viewer permission is insufficient for the approval cell poll by Agent 3 because it must read a specific named range).
Required scopes
https://www.googleapis.com/auth/spreadsheets (read and write to Sheets) | https://www.googleapis.com/auth/drive.file (export to PDF via Drive API)
Webhook / trigger setup
Agent 3 polls the approval named range (ApprovalStatus cell, defined as a named range FORECAST_APPROVAL in the sheet) on a 5-minute interval after Agent 2 completes its write. When the cell value equals the string 'Approved' (case-insensitive match), Agent 3 proceeds. Do not use Google Apps Script triggers as they introduce a dependency outside the automation platform.
Required configuration
Store in credential vault: GOOGLE_SERVICE_ACCOUNT_JSON, SHEETS_SPREADSHEET_ID, SHEETS_DATA_RANGE (e.g. 'ForecastData!A2:Z'), SHEETS_APPROVAL_NAMED_RANGE ('FORECAST_APPROVAL'), SHEETS_SUMMARY_TAB_NAME (e.g. 'Summary'). SHEETS_SPREADSHEET_ID must never be hardcoded in workflow nodes. The master sheet must have stable column positions; document the column index map in the field mappings section of this spec.
Endpoints used
PUT /v4/spreadsheets/{spreadsheetId}/values/{range}?valueInputOption=USER_ENTERED (Agent 2 write) | GET /v4/spreadsheets/{spreadsheetId}/values/{namedRange} (Agent 3 approval poll) | POST /v3/files/{fileId}/export?mimeType=application/pdf (Agent 3 PDF export via Drive API)
Rate limits
Sheets API: 300 read/write requests per minute per project; 60 requests per minute per user. At current volume (1 batch write per week, 1 poll every 5 minutes for up to 4 hours) peak usage is well within limits. No throttling required at current volume.
Constraints
The Google Sheet formula structure must not be overwritten by the data write. Agent 2 must write only into the data input rows (not formula rows). Column positions must be validated against SHEETS_DATA_RANGE before each write. If the sheet structure changes, SHEETS_DATA_RANGE must be updated in the credential store and the field mapping table re-validated.
// Input (Agent 2 write)
categorised_payload: CategorisedTransaction[]
flagged_items: FlaggedTransaction[]
SHEETS_SPREADSHEET_ID: string
SHEETS_DATA_RANGE: string
// Input (Agent 3 poll)
SHEETS_APPROVAL_NAMED_RANGE: string
// Output (Agent 3 PDF export)
pdf_binary: Buffer  // exported from SHEETS_SUMMARY_TAB_NAME
pdf_filename: string  // e.g. 'CashForecast_2024-06-17.pdf'
Integration and API SpecPage 1 of 3
FS-DOC-05Technical
Gmail

Used by Agent 3 (Distribution Agent) to send the approved forecast PDF to the stakeholder distribution list. Sends from a designated service address using delegated OAuth credentials. No inbound email processing is required.

Auth method
OAuth 2.0 with domain-wide delegation. The service account created for Google Sheets is granted domain-wide delegation in Google Workspace Admin. The automation platform impersonates the designated sender address (e.g. forecasts@[YourCompany.com]) using the GMAIL_SENDER_ADDRESS credential. Alternatively, a dedicated Gmail OAuth client can be used with a shared mailbox; store tokens as GMAIL_ACCESS_TOKEN and GMAIL_REFRESH_TOKEN.
Required scopes
https://www.googleapis.com/auth/gmail.send
Webhook / trigger setup
No inbound Gmail webhook. Agent 3 is triggered by the approval cell state in Google Sheets, not by an incoming email. Gmail is an output-only integration in this automation.
Required configuration
Store in credential vault: GMAIL_SENDER_ADDRESS, GMAIL_RECIPIENT_LIST (comma-separated or JSON array of email addresses), GMAIL_SUBJECT_TEMPLATE (e.g. 'Cash Flow Forecast: week of {run_date}'), GMAIL_BODY_TEMPLATE_ID (reference to the template stored in the platform's template library, not hardcoded inline). The recipient list must be stored in the credential vault so it can be updated without a code change.
Endpoints used
POST /gmail/v1/users/{userId}/messages/send // with multipart/related body containing the PDF attachment as base64-encoded content
Rate limits
Gmail API: 250 quota units per user per second; sending a message with attachment costs 100 units. At 1 send per week the rate limit is not a concern. Daily sending limit for Google Workspace is 2,000 messages per day; this automation sends 1.
Constraints
Attachment size limit is 25 MB per message via the Gmail API. The exported forecast PDF is expected to be under 2 MB. If the PDF export exceeds 10 MB, switch to attaching a Google Drive shareable link instead of an inline attachment. The GMAIL_RECIPIENT_LIST must be reviewed and updated by the process owner if stakeholders change; this is not self-maintaining.
// Input
pdf_binary: Buffer  (from Google Sheets PDF export)
pdf_filename: string
run_date: ISO-8601 string
GMAIL_SENDER_ADDRESS: string
GMAIL_RECIPIENT_LIST: string[]
GMAIL_SUBJECT_TEMPLATE: string
// Output
gmail_message_id: string  // returned by Gmail API on success
gmail_thread_id: string
Slack

Used by Agent 3 (Distribution Agent) to post a formatted cash summary message to the finance channel immediately after the Gmail send succeeds. Uses a Slack Bot Token with a dedicated app installed in the workspace.

Auth method
OAuth 2.0 Bot Token. Create a Slack app at api.slack.com/apps, add the required bot token scopes, install the app to the workspace, and store the Bot User OAuth Token as SLACK_BOT_TOKEN in the credential vault. Do not use legacy incoming webhooks if the workspace supports the current app model; Bot Token allows channel targeting at runtime.
Required scopes
chat:write | chat:write.public (if posting to channels the bot has not joined) | files:write (only required if attaching the PDF directly to Slack; not used in the standard build)
Webhook / trigger setup
No inbound Slack events are consumed by this automation. Outbound only. Store SLACK_FINANCE_CHANNEL_ID (the channel ID, not the display name, e.g. C04XXXXXXXX) in the credential vault. Channel ID is stable even if the channel is renamed; display names are not safe to hardcode.
Required configuration
Store in credential vault: SLACK_BOT_TOKEN, SLACK_FINANCE_CHANNEL_ID, SLACK_MESSAGE_TEMPLATE_ID (reference to the Block Kit JSON template stored in the platform template library). The Block Kit template must include placeholder tokens for: {opening_balance}, {week4_projected_balance}, {flagged_weeks_count}, {run_date}, {approval_timestamp}.
Endpoints used
POST /api/chat.postMessage // with channel, blocks (Block Kit JSON), and text fallback fields
Rate limits
Slack Tier 3: 50 calls/minute for chat.postMessage. At 1 call per weekly run this is trivially within limits. No throttling needed.
Constraints
Block Kit message JSON must be validated before deployment; malformed Block Kit silently falls back to the text field without error in some Slack clients. The text fallback field must always be populated with a plain-text summary for notification previews and accessibility. If the finance channel is archived or the bot is removed, Agent 3 will receive a channel_not_found error; this must trigger a fallback alert to the process owner.
// Input
opening_balance: number  (currency, from categorised payload)
week4_projected_balance: number
flagged_weeks_count: integer
run_date: ISO-8601 string
approval_timestamp: ISO-8601 string
SLACK_BOT_TOKEN: string
SLACK_FINANCE_CHANNEL_ID: string
// Output
slack_ts: string   // message timestamp, used as message ID
slack_channel: string  // echoed channel ID confirming delivery

03Field mappings between tools

The following tables document the field-level mapping for each agent handoff in the workflow. All field names are shown exactly as they appear in the API response or the platform data model. Use these mappings as the authoritative reference when building transformation steps in the orchestration layer.

Handoff 1: Data Collection Agent output to Categorisation Agent input (Xero and Stripe to categorisation logic)

Source tool
Source field
Destination tool
Destination field
Xero
`BankTransaction.BankTransactionID`
Categorisation Agent
`transaction_id`
Xero
`BankTransaction.Date`
Categorisation Agent
`transaction_date`
Xero
`BankTransaction.Total`
Categorisation Agent
`amount`
Xero
`BankTransaction.Type`
Categorisation Agent
`transaction_type`
Xero
`BankTransaction.Reference`
Categorisation Agent
`reference`
Xero
`BankTransaction.LineItems[0].AccountCode`
Categorisation Agent
`xero_account_code`
Xero
`BankTransaction.LineItems[0].Description`
Categorisation Agent
`line_description`
Xero
`Contact.Name`
Categorisation Agent
`contact_name`
Xero
`AgedReceivables.Aged[*].Outstanding`
Categorisation Agent
`ar_bucket_amount`
Xero
`AgedReceivables.Aged[*].AgingPeriodType`
Categorisation Agent
`ar_bucket_label`
Xero
`Invoice.DueDate`
Categorisation Agent
`bill_due_date`
Xero
`Invoice.AmountDue`
Categorisation Agent
`bill_amount_due`
Stripe
`Payout.id`
Categorisation Agent
`payout_id`
Stripe
`Payout.amount`
Categorisation Agent
`payout_amount_cents`
Stripe
`Payout.arrival_date`
Categorisation Agent
`payout_arrival_date`
Stripe
`Payout.status`
Categorisation Agent
`payout_status`

Handoff 2: Categorisation Agent output to Google Sheets write (Categorisation Agent to master forecast sheet)

Source tool
Source field
Destination tool
Destination field
Categorisation Agent
`transaction_id`
Google Sheets
`ForecastData!A{row}`
Categorisation Agent
`transaction_date`
Google Sheets
`ForecastData!B{row}`
Categorisation Agent
`amount`
Google Sheets
`ForecastData!C{row}`
Categorisation Agent
`assigned_forecast_line`
Google Sheets
`ForecastData!D{row}`
Categorisation Agent
`confidence_score`
Google Sheets
`ForecastData!E{row}`
Categorisation Agent
`flagged`
Google Sheets
`ForecastData!F{row}`
Categorisation Agent
`flag_reason`
Google Sheets
`ForecastData!G{row}`
Categorisation Agent
`contact_name`
Google Sheets
`ForecastData!H{row}`
Categorisation Agent
`payout_amount_cents` / 100
Google Sheets
`ForecastData!I{row}`
Categorisation Agent
`payout_arrival_date`
Google Sheets
`ForecastData!J{row}`
Categorisation Agent
`ar_bucket_amount` (per bucket)
Google Sheets
`ARAging!B2:B6`
Categorisation Agent
`bill_due_date`
Google Sheets
`BillsPayable!A{row}`
Categorisation Agent
`bill_amount_due`
Google Sheets
`BillsPayable!B{row}`
Categorisation Agent
`run_timestamp`
Google Sheets
`Metadata!B1`

Handoff 3: Google Sheets approval signal to Distribution Agent (approval trigger to PDF export and outbound delivery)

Source tool
Source field
Destination tool
Destination field
Google Sheets
`FORECAST_APPROVAL` named range value
Distribution Agent
`approval_status`
Google Sheets
`Metadata!B1` (run_timestamp)
Distribution Agent
`run_date`
Google Sheets
`Summary!B3` (opening_balance)
Distribution Agent
`opening_balance`
Google Sheets
`Summary!B7` (week4_projected_balance)
Distribution Agent
`week4_projected_balance`
Google Sheets
`Summary!B10` (flagged_weeks_count)
Distribution Agent
`flagged_weeks_count`
Google Sheets (PDF export)
Drive API binary stream
Gmail
`attachment.data` (base64)
Google Sheets (PDF export)
Filename constructed from run_date
Gmail
`attachment.filename`
Distribution Agent
`opening_balance`
Slack
`{opening_balance}` in Block Kit template
Distribution Agent
`week4_projected_balance`
Slack
`{week4_projected_balance}` in Block Kit template
Distribution Agent
`flagged_weeks_count`
Slack
`{flagged_weeks_count}` in Block Kit template
Distribution Agent
`approval_timestamp`
Slack
`{approval_timestamp}` in Block Kit template
Column positions in Google Sheets (ForecastData!A through J) must be confirmed against the live master sheet before the first production write. If the sheet owner adds or removes columns, SHEETS_DATA_RANGE and the field mapping above must be updated before the next run. Treat the column index map as a configuration artifact, not a code constant.
Integration and API SpecPage 2 of 3
FS-DOC-05Technical

04Build stack and orchestration

Orchestration layout
One workflow per agent: three discrete workflow definitions in the automation platform (Data Collection Workflow, Categorisation Workflow, Distribution Workflow). Workflows communicate via a shared internal data bus or staging object (platform-native). A shared credential store is the single source of truth for all API keys, tokens, and configuration IDs. No credentials appear in workflow node configuration fields.
Agent 1 trigger mechanism
Cron schedule: every Monday at 08:00 in the business's local timezone (timezone stored as SCHEDULE_TIMEZONE in credential store). Poll-based; no inbound webhook. The trigger node fires the Data Collection Workflow unconditionally; failures are handled by the retry engine, not by skipping the run.
Agent 2 trigger mechanism
Event-based: Agent 2 (Categorisation Workflow) is triggered by the successful completion event of Agent 1. The structured data payload from Agent 1 is passed as the trigger input. No polling interval; execution is sequential and immediate.
Agent 3 trigger mechanism
Polling with conditional exit: Agent 3 (Distribution Workflow) begins polling the Google Sheets FORECAST_APPROVAL named range every 5 minutes after Agent 2 completes. Poll continues for a maximum of 8 hours (configurable via APPROVAL_TIMEOUT_HOURS in credential store). On timeout, a Slack alert is sent to the process owner and the run is marked as awaiting approval. No signature validation is required for this poll pattern; the Sheets API call is authenticated via the service account.
Webhook signature validation
Not applicable for the current trigger patterns (cron and poll). If Stripe webhooks are added in a future iteration, validate the Stripe-Signature header using HMAC-SHA256 with STRIPE_WEBHOOK_SECRET before processing any event payload. Reject and log any request that fails signature validation.
Credential store structure
All secrets stored in the automation platform's native encrypted credential vault. See code block below for the full credential manifest.
Data retention
Workflow execution logs retained for 30 days in the platform. The Google Sheet provides the permanent timestamped record. No financial data is persisted in the automation platform beyond the current run's execution context.
Credential store manifest: all 25 entries must be provisioned before the first production run
// Credential store manifest
// All entries are encrypted at rest in the platform credential vault
// Format: KEY_NAME : type : owner agent(s)

XERO_CLIENT_ID           : string  : Agent 1
XERO_CLIENT_SECRET       : string  : Agent 1
XERO_TENANT_ID           : string  : Agent 1
XERO_ACCESS_TOKEN        : string  : Agent 1  // rotated automatically on refresh
XERO_REFRESH_TOKEN       : string  : Agent 1  // rotated automatically on refresh

STRIPE_RESTRICTED_KEY    : string  : Agent 1
STRIPE_WEBHOOK_SECRET    : string  : future use only (not active in Standard build)

GOOGLE_SERVICE_ACCOUNT_JSON : json : Agent 2, Agent 3
SHEETS_SPREADSHEET_ID    : string  : Agent 2, Agent 3
SHEETS_DATA_RANGE        : string  : Agent 2  // e.g. 'ForecastData!A2:J500'
SHEETS_APPROVAL_NAMED_RANGE : string : Agent 3  // 'FORECAST_APPROVAL'
SHEETS_SUMMARY_TAB_NAME  : string  : Agent 3  // e.g. 'Summary'

GMAIL_SENDER_ADDRESS     : string  : Agent 3
GMAIL_RECIPIENT_LIST     : json    : Agent 3  // array of email strings
GMAIL_SUBJECT_TEMPLATE   : string  : Agent 3
GMAIL_BODY_TEMPLATE_ID   : string  : Agent 3

SLACK_BOT_TOKEN          : string  : Agent 3
SLACK_FINANCE_CHANNEL_ID : string  : Agent 3
SLACK_MESSAGE_TEMPLATE_ID : string : Agent 3

SCHEDULE_TIMEZONE        : string  : Agent 1  // e.g. 'America/New_York'
APPROVAL_TIMEOUT_HOURS   : integer : Agent 3  // default: 8
OWNER_ALERT_EMAIL        : string  : Agent 1, Agent 3  // fallback alert recipient
MAX_RETRY_ATTEMPTS       : integer : Agent 1  // default: 3
RETRY_BACKOFF_BASE_SECONDS : integer : Agent 1  // default: 60

05Error handling and retry logic

Every integration point has a defined failure behaviour. Unhandled exceptions must never fail silently. Any error not matched by the table below must be caught by the global exception handler, logged with full execution context (run ID, timestamp, agent name, error code, response body), and trigger an alert to OWNER_ALERT_EMAIL before the workflow terminates.

Integration
Scenario
Required behaviour
Xero (Agent 1)
HTTP 401 Unauthorized on API call
Attempt token refresh using XERO_REFRESH_TOKEN. If refresh succeeds, retry the original call immediately. If refresh returns 401 or 400, halt the run, log the error, and send an alert to OWNER_ALERT_EMAIL with the instruction to re-authorise the Xero OAuth connection. Do not proceed to Agent 2.
Xero (Agent 1)
HTTP 429 Too Many Requests
Pause execution for 60 seconds (RETRY_BACKOFF_BASE_SECONDS). Retry the failed call. Repeat up to MAX_RETRY_ATTEMPTS (default 3). If all retries fail, halt the run and alert OWNER_ALERT_EMAIL with the specific endpoint and page number that failed.
Xero (Agent 1)
Pagination returns fewer records than expected (possible mid-run data change)
Log a warning with the expected vs received record count. Continue processing available records. Append a data-quality warning to the flagged_items list so the finance lead can see the discrepancy during review. Do not halt the run.
Stripe (Agent 1)
HTTP 401 or 403 on payout endpoint
Log the error with full response body. Halt the Data Collection run. Alert OWNER_ALERT_EMAIL that the Stripe restricted key may have been revoked and must be regenerated and updated in the credential store. Do not produce a partial data payload.
Stripe (Agent 1)
HTTP 503 or network timeout
Retry with exponential backoff: 60 s, 120 s, 240 s (3 attempts). If all retries fail, continue the run with a null stripe_payouts array and append a warning to flagged_items noting that Stripe payout data is unavailable for this run. Alert OWNER_ALERT_EMAIL.
Google Sheets (Agent 2)
HTTP 403 Forbidden on write call
Indicates the service account has lost editor access to the spreadsheet. Halt the categorisation write. Alert OWNER_ALERT_EMAIL with the spreadsheet ID and instruction to re-share the sheet with the service account email. Do not write partial data.
Google Sheets (Agent 2)
Column position mismatch detected (SHEETS_DATA_RANGE returns unexpected column count)
Halt the write immediately. Do not overwrite existing sheet data with misaligned values. Log the expected vs actual column count. Alert OWNER_ALERT_EMAIL that the sheet structure may have changed and SHEETS_DATA_RANGE must be reviewed. This is a breaking error.
Google Sheets (Agent 3)
Approval poll exceeds APPROVAL_TIMEOUT_HOURS without detecting 'Approved'
Stop polling. Log the timeout event. Post a Slack message to SLACK_FINANCE_CHANNEL_ID informing the finance lead that the forecast is awaiting approval. Send an email alert to OWNER_ALERT_EMAIL. Mark the run status as 'Awaiting Approval' in the execution log. Do not send the forecast distribution.
Gmail (Agent 3)
HTTP 403 or send quota exceeded on message send
Retry once after 30 seconds. If the second attempt fails, log the error with the full Gmail API response. Alert OWNER_ALERT_EMAIL by posting to Slack (fallback channel if Gmail is unavailable) with the PDF export link from Google Drive as an alternative distribution method. Do not silently drop the distribution.
Gmail (Agent 3)
PDF export from Drive API returns empty or zero-byte file
Do not send an empty attachment. Halt the Gmail send. Alert OWNER_ALERT_EMAIL with the run ID and instruction to manually export the Summary tab. Log the Drive API response for diagnosis.
Slack (Agent 3)
channel_not_found or not_in_channel error on chat.postMessage
Log the Slack API error response. Attempt to send the cash summary as a plain-text email to GMAIL_RECIPIENT_LIST as a fallback. Alert OWNER_ALERT_EMAIL that the Slack bot has lost access to the finance channel and must be re-invited. Do not fail silently.
All agents
Unhandled exception (any error not matched above)
Global exception handler catches the error. Log run ID, agent name, node name, timestamp, error type, and full stack trace. Send an immediate alert to OWNER_ALERT_EMAIL with a plain-English summary of where the run stopped. Mark the run as failed in the execution log. Never allow an unhandled exception to exit without logging and alerting.
Retry logic applies to transient network and rate-limit errors only. Authentication failures (401, 403) must not be retried more than once after a token refresh attempt. Retrying a credential error repeatedly can lock an API account or exhaust token refresh limits. Fail fast and alert on auth errors.

For questions about this specification or to report an inconsistency before build, contact the FullSpec team at support@gofullspec.com with the process name and document reference FS-DOC-05.

Integration and API SpecPage 3 of 3

More documents for this process

Every document generated for Cash Flow Forecasting.

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