FS-DOC-05Technical
Integration and API Spec
Budget Planning and Approval
[YourCompany.com] · Management Department · Prepared by FullSpec · [Today's Date]
This document defines the exact integration requirements, authentication methods, API scopes, field mappings, credential store contents, and error handling rules for the Budget Planning and Approval automation. It is written for the FullSpec build team and assumes working familiarity with REST APIs, OAuth 2.0 flows, and webhook configuration. Every integration point listed here must be fully validated in a sandbox environment before any production credential is connected. The orchestration layer is referred to generically throughout; no specific build platform is assumed at this stage.
01Tool inventory
Tool
Role in automation
Auth method
Min plan required
Used by agents
Orchestration layer
Workflow automation platform hosting all three agent workflows, credential store, and retry logic
Internal (platform auth)
Paid tier with webhook and API call support
All agents
Google Forms
Standardised department budget submission input; responses written to linked Google Sheet
Google OAuth 2.0 (service account)
Google Workspace (any tier)
Agent 1, Agent 2
Google Sheets
Master budget tracker, submission status log, consolidated budget output, variance flagging
Google OAuth 2.0 (service account)
Google Workspace (any tier)
Agent 1, Agent 2, Agent 3
Xero
Pull prior period actuals via API for variance column population
OAuth 2.0 (authorization code flow)
Xero Starter or above
Agent 2
Slack
Deadline reminder messages to department heads; completion notification to finance channel
Slack Bot Token (OAuth 2.0)
Slack Free or above (paid for guaranteed delivery)
Agent 1, Agent 3
DocuSign
Generate and dispatch signing envelope in configured order; capture completion event via webhook
OAuth 2.0 (JWT grant or authorization code)
DocuSign Business Pro or eSignature Standard
Agent 3
Google Drive
Archive signed budget document to period-specific folder; update master sheet with archive URL
Google OAuth 2.0 (service account)
Google Workspace (any tier)
Agent 3
Before you connect anything: sandbox-test every connection using non-production credentials before any live credential is entered into the credential store. For Xero, use the Xero Demo Company. For DocuSign, use the developer sandbox at account-d.docusign.com. For Google Workspace, use a dedicated service account with test-only Sheet and Drive access. No production data should be read or written until all test cases in the Test and QA Plan have passed.
Integration and API SpecPage 1 of 4
FS-DOC-05Technical
02Per-tool integration detail
Google Forms
Receives standardised budget submissions from department heads. The form is pre-populated with department name and prior period actuals pulled from the master Google Sheet. Responses feed directly into the linked response Sheet tab consumed by Agent 2.
Auth method
Google OAuth 2.0 using a dedicated service account. The service account JSON key is stored in the credential store (key: GOOGLE_SA_KEY). The service account must be granted Editor access to the linked response Sheet and Viewer access to the master Sheet.
Required scopes
https://www.googleapis.com/auth/forms.body, https://www.googleapis.com/auth/forms.responses.readonly, https://www.googleapis.com/auth/spreadsheets
Webhook / trigger setup
Google Forms does not natively support outbound webhooks. Responses are monitored by polling the linked Google Sheet responses tab (see Google Sheets entry). Alternatively, an Apps Script on-form-submit trigger can POST to the orchestration layer webhook endpoint; this is the preferred approach and requires the Apps Script to be published under the service account.
Required configuration
Form ID stored as GFORMS_BUDGET_FORM_ID in the credential store. Pre-population of department name and prior actuals is achieved via pre-filled URL generation using the form's field entry IDs (e.g. entry.123456789 for department name). Entry IDs must be extracted from the form HTML and stored as GFORMS_ENTRY_DEPT and GFORMS_ENTRY_ACTUALS. The form must include fields: Department Name (short text), Cost Category (dropdown, locked list), Budget Line Description (short text), Amount Requested (number), Notes (long text, optional).
Rate limits
Google Forms API: 500 requests per 100 seconds per project. At current volume (1 to 4 cycles per year, 6 to 15 submissions per cycle), peak call volume is well under 50 requests per cycle. No throttling required.
Constraints
Form responses cannot be edited programmatically after submission; any correction requires a resubmission link to be issued to the department head. Form sharing must be set to 'Restricted to organisation' to prevent external submissions.
// Output (to Google Sheets response tab)
response.timestamp -> Column A: Timestamp
response.department_name -> Column B: Department
response.cost_category -> Column C: Category
response.line_description-> Column D: Description
response.amount_requested-> Column E: Amount
response.notes -> Column F: Notes
Google Sheets
Central data store for the entire workflow. Three key tabs are used: (1) SubmissionTracker, (2) FormResponses (linked from Google Forms), and (3) MasterBudget. The orchestration layer reads and writes to all three tabs across all three agents.
Auth method
Google OAuth 2.0 service account. Same GOOGLE_SA_KEY credential as Google Forms. Service account must have Editor access to the master workbook.
Required scopes
https://www.googleapis.com/auth/spreadsheets, https://www.googleapis.com/auth/drive.file
Webhook / trigger setup
Agent 1 polls the SubmissionTracker tab every 30 minutes during active cycles to check deadline proximity and missing submissions. The orchestration layer computes the 48-hour and 24-hour windows from the deadline value stored in cell CONFIG!B2. Agent 2 is triggered by an Apps Script POST webhook when all submissions are received (status column all set to 'Submitted') or when the deadline timestamp passes.
Required configuration
Spreadsheet ID stored as GSHEETS_MASTER_ID. Tab names must match exactly: SubmissionTracker, FormResponses, MasterBudget, CONFIG. CONFIG tab structure: B1 = cycle name, B2 = deadline ISO timestamp, B3 = variance threshold percentage (e.g. 0.15 for 15%), B4 = finance manager Slack user ID, B5 = finance Slack channel ID. SubmissionTracker columns: A = Department, B = Submission Status (Pending/Submitted/Late), C = Submission Timestamp, D = Form Response Row Reference, E = Reminder 48h Sent (TRUE/FALSE), F = Reminder 24h Sent (TRUE/FALSE). MasterBudget columns: A = Department, B = Category, C = Description, D = Submitted Amount, E = Prior Actuals (from Xero), F = Variance Amount, G = Variance Pct, H = Flag (TRUE/FALSE), I = Finance Cleared (TRUE/FALSE).
Rate limits
Sheets API v4: 300 write requests per minute per project, 60 requests per minute per user. At current volume, batch writes per consolidation cycle are well under 100 requests. No throttling required. Use batchUpdate for all multi-cell writes to minimise call count.
Constraints
Sheets API does not support real-time push notifications natively. All change detection must be via polling or Apps Script triggers. Cell references must never be hardcoded in the orchestration layer; always use named ranges or read from CONFIG tab.
// Read (Agent 1): SubmissionTracker tab
SubmissionTracker!A:F -> department list, status, reminder flags
CONFIG!B2 -> deadline_timestamp
// Write (Agent 1): SubmissionTracker tab
SubmissionTracker!B{row} -> 'Late' if deadline passed
SubmissionTracker!E{row} -> TRUE after 48h reminder sent
SubmissionTracker!F{row} -> TRUE after 24h reminder sent
// Read (Agent 2): FormResponses tab
FormResponses!A:F -> all validated submission rows
// Write (Agent 2): MasterBudget tab
MasterBudget!A:I -> consolidated rows with variance flags
// Write (Agent 3): MasterBudget!I{row}
MasterBudget!I{row} -> TRUE after finance marks cleared
MasterBudget + Drive URL -> appended to archive log rowXero
Source of prior period actuals used to populate variance columns in the MasterBudget tab. The integration reads account transaction data scoped to the relevant tracking categories and reporting period. No write operations are performed against Xero.
Auth method
OAuth 2.0 authorization code flow. Access token and refresh token stored in the credential store (keys: XERO_ACCESS_TOKEN, XERO_REFRESH_TOKEN). Tokens expire after 30 minutes; the orchestration layer must implement token refresh using XERO_CLIENT_ID and XERO_CLIENT_SECRET before each API call. Xero tenant ID stored as XERO_TENANT_ID.
Required scopes
openid, profile, email, accounting.reports.read, accounting.settings.read, offline_access
Webhook / trigger setup
No inbound webhook required. Agent 2 calls the Xero API on demand when the consolidation run fires. No Xero webhook configuration is needed for this integration.
Required configuration
XERO_TENANT_ID must be set in the credential store. The reporting period (month range) is computed dynamically from CONFIG!B1 (cycle name, e.g. 'Q1 2025') and passed as fromDate and toDate parameters to the Profit and Loss report endpoint: GET /api.xro/2.0/Reports/ProfitAndLoss?fromDate={fromDate}&toDate={toDate}&trackingCategoryID={XERO_TRACKING_ID}. The tracking category ID for cost centre mapping must be set as XERO_TRACKING_ID in the credential store. Cost centre labels in Xero must match the Category dropdown values in the Google Form exactly; any mismatch must be resolved with the finance manager before go-live.
Rate limits
Xero API: 60 calls per minute, 5000 calls per day (Standard plan). The consolidation agent makes at most 15 to 20 API calls per cycle (one per cost centre plus token refresh calls). No throttling required. Add a 1-second delay between sequential calls as a precaution.
Constraints
Xero OAuth tokens must be refreshed before expiry; the orchestration layer must catch 401 responses and trigger a token refresh before retrying. The Xero app must be connected to only one Xero organisation; confirm the correct tenant with the finance manager before connecting. Read-only scope only; no budget or journal write-back is performed in this build.
// API call (Agent 2)
GET /api.xro/2.0/Reports/ProfitAndLoss
?fromDate={period_start}
?toDate={period_end}
?trackingCategoryID={XERO_TRACKING_ID}
// Mapped output -> MasterBudget tab
Report.Rows[].Cells[].Value -> MasterBudget!E (Prior Actuals per cost centre)Slack
Used by Agent 1 to send targeted submission deadline reminders to individual department heads, and by Agent 3 to post a completion notification to the finance channel once the signed document is archived.
Auth method
Slack Bot Token (xoxb-...) stored as SLACK_BOT_TOKEN in the credential store. The bot must be installed to the workspace and invited to the relevant channels. User IDs for department heads are stored in the SubmissionTracker!G column (populated during setup). Finance channel ID stored as GSHEETS_CONFIG value CONFIG!B5.
Required scopes
chat:write, users:read, users:read.email, channels:read, im:write (for direct messages to department heads)
Webhook / trigger setup
No inbound webhook required from Slack. Agent 1 uses the Slack Web API chat.postMessage method to send direct messages and channel posts. Message payloads use Block Kit JSON for structured formatting.
Required configuration
SLACK_BOT_TOKEN in credential store. Department head Slack user IDs must be populated in SubmissionTracker!G before the first cycle runs. Finance manager Slack user ID stored as CONFIG!B4. Finance channel ID stored as CONFIG!B5. Reminder message templates are stored as static strings in the orchestration layer workflow configuration; they reference {department_name} and {deadline_datetime} as dynamic variables.
Rate limits
Slack Web API: Tier 3 methods (chat.postMessage) allow 50 calls per minute. At 15 department submissions maximum per cycle with two reminder windows, peak is 30 messages per cycle. No throttling required.
Constraints
The bot must be a member of any channel it posts to. Direct messages require im:write scope and the recipient must have accepted the bot's DM. If a user ID cannot be resolved, the orchestration layer must fall back to posting in the finance channel with the department name mentioned explicitly.
// Agent 1: deadline reminder DM
POST /api/slack/chat.postMessage
channel: {dept_head_user_id}
text: 'Reminder: {department_name} budget submission due {deadline_datetime}'
// Agent 3: completion notification
POST /api/slack/chat.postMessage
channel: {finance_channel_id}
text: 'Budget approval complete. Signed document archived: {drive_url}'DocuSign
Used by Agent 3 to generate a signing envelope from the consolidated budget summary document, dispatch it to signatories in the configured order, and receive a completion webhook event when all signatures are captured.
Auth method
OAuth 2.0 JWT grant flow (recommended for server-to-server automation). RSA private key stored as DOCUSIGN_RSA_PRIVATE_KEY in the credential store. Integration key stored as DOCUSIGN_INTEGRATION_KEY. Account ID stored as DOCUSIGN_ACCOUNT_ID. Base URI stored as DOCUSIGN_BASE_URI (production: https://{subdomain}.docusign.net; sandbox: https://demo.docusign.net).
Required scopes
signature, impersonation (required for JWT grant). The user being impersonated must have granted consent to the integration key via the consent URL before the first run.
Webhook / trigger setup
A DocuSign Connect webhook (event notification) must be configured at the account level to POST envelope status events to the orchestration layer inbound webhook endpoint. Events to subscribe: envelope-completed, envelope-declined, envelope-voided. The orchestration layer endpoint must validate the HMAC-SHA256 signature on each incoming request using the Connect HMAC secret stored as DOCUSIGN_CONNECT_HMAC_SECRET in the credential store.
Required configuration
DOCUSIGN_SIGNING_ORDER: a JSON array of signer objects defining name, email, and routing order (e.g. [{name:'Finance Manager', email:'...', order:1},{name:'CEO', email:'...', order:2}]). Stored as DOCUSIGN_SIGNERS in the credential store. Template ID for the budget envelope stored as DOCUSIGN_TEMPLATE_ID (if using a pre-built template); otherwise the orchestration layer generates the document from the MasterBudget tab and attaches it as a base64-encoded PDF. Envelope subject line: 'Budget Approval Required: {cycle_name}'. Expiry: 7 days, after which the orchestration layer triggers the fallback reminder logic.
Rate limits
DocuSign eSignature API: 1000 API calls per hour on Business Pro. At 1 to 4 cycles per year with at most 5 API calls per cycle (create envelope, get status, void if needed), usage is negligible. No throttling required.
Constraints
Envelope creation requires the document to be provided as a base64-encoded PDF or a pre-configured template. The signing order must be validated against the company's delegation of authority policy before build. Declined or voided envelopes must trigger an alert to the finance manager and must not proceed to archiving.
// Agent 3: create envelope
POST /v2.1/accounts/{DOCUSIGN_ACCOUNT_ID}/envelopes
body.documents[0].documentBase64 -> base64 PDF of MasterBudget summary
body.recipients.signers -> DOCUSIGN_SIGNERS array
body.envelopeDefinition.status -> 'sent'
// Inbound webhook (Connect event)
POST {orchestration_webhook_endpoint}
event.envelopeId -> matched to active cycle
event.status -> 'completed' | 'declined' | 'voided'
event.completedDateTime -> written to MasterBudget archive logGoogle Drive
Used by Agent 3 to upload the signed budget document (downloaded from DocuSign after envelope completion) to the correct period-specific folder and to return the shareable file URL for the Slack completion notification.
Auth method
Google OAuth 2.0 service account. Same GOOGLE_SA_KEY credential. Service account must have Editor access to the parent archive folder. Folder ID for the parent archive is stored as GDRIVE_ARCHIVE_FOLDER_ID in the credential store.
Required scopes
https://www.googleapis.com/auth/drive.file, https://www.googleapis.com/auth/drive.metadata.readonly
Webhook / trigger setup
No inbound webhook from Google Drive is required. Agent 3 performs upload after receiving the DocuSign Connect completion event.
Required configuration
GDRIVE_ARCHIVE_FOLDER_ID: ID of the parent folder (e.g. 'Budget Approvals'). Agent 3 creates a sub-folder named '{cycle_name} Signed Budget' under this parent if it does not already exist, then uploads the signed PDF with filename format: BudgetApproval_{cycle_name}_{ISO_date}.pdf. The resulting file's webViewLink is stored in MasterBudget archive log and posted to Slack.
Rate limits
Drive API v3: 1000 requests per 100 seconds per project. Upload calls per cycle: 2 (create folder check plus file upload). No throttling required.
Constraints
The service account must not be granted broader Drive access than drive.file scope to limit data exposure. Folder sharing permissions must be configured manually by the Workspace admin; the service account cannot modify sharing settings without broader scope. If the upload fails, the orchestration layer must retain the downloaded PDF in temporary storage and retry before raising an alert.
// Agent 3: check or create sub-folder
GET /drive/v3/files?q='GDRIVE_ARCHIVE_FOLDER_ID' in parents and name='{cycle_name} Signed Budget'
POST /drive/v3/files (if folder not found)
body.name -> '{cycle_name} Signed Budget'
body.mimeType -> 'application/vnd.google-apps.folder'
body.parents -> [GDRIVE_ARCHIVE_FOLDER_ID]
// Agent 3: upload signed PDF
POST /upload/drive/v3/files?uploadType=multipart
metadata.name -> 'BudgetApproval_{cycle_name}_{ISO_date}.pdf'
metadata.parents -> [sub_folder_id]
media body -> signed PDF binary from DocuSign
// Output
file.webViewLink -> SLACK completion message + MasterBudget archive logIntegration and API SpecPage 2 of 4
FS-DOC-05Technical
03Field mappings between tools
The tables below document every field handoff between tools at each agent boundary. Source and destination field names are given in exact monospace format as they appear in the API response or Sheet column header. All Sheet references assume the workbook identified by GSHEETS_MASTER_ID.
Agent 1 handoff: Google Forms response tab to SubmissionTracker (Submission Coordinator Agent)
Source tool
Source field
Destination tool
Destination field
Google Forms (via Sheet)
`FormResponses!A` (Timestamp)
Google Sheets
`SubmissionTracker!C` (Submission Timestamp)
Google Forms (via Sheet)
`FormResponses!B` (Department Name)
Google Sheets
`SubmissionTracker!A` (Department)
Google Forms (via Sheet)
`FormResponses!B` (Department Name)
Slack
`chat.postMessage.text` {department_name}
Google Sheets (CONFIG)
`CONFIG!B2` (deadline_timestamp)
Slack
`chat.postMessage.text` {deadline_datetime}
Google Sheets
`SubmissionTracker!B` (Submission Status)
Slack
Condition gate: send DM only if value = 'Pending' or 'Late'
Google Sheets
`SubmissionTracker!G` (Dept Head Slack ID)
Slack
`chat.postMessage.channel`
Agent 2 handoff: FormResponses and Xero to MasterBudget (Budget Consolidation Agent)
Source tool
Source field
Destination tool
Destination field
Google Forms (via Sheet)
`FormResponses!B` (Department Name)
Google Sheets
`MasterBudget!A` (Department)
Google Forms (via Sheet)
`FormResponses!C` (Cost Category)
Google Sheets
`MasterBudget!B` (Category)
Google Forms (via Sheet)
`FormResponses!D` (Line Description)
Google Sheets
`MasterBudget!C` (Description)
Google Forms (via Sheet)
`FormResponses!E` (Amount Requested)
Google Sheets
`MasterBudget!D` (Submitted Amount)
Xero
`Report.Rows[].Cells[1].Value` (actuals per category)
Google Sheets
`MasterBudget!E` (Prior Actuals)
Google Sheets (computed)
`MasterBudget!D` minus `MasterBudget!E`
Google Sheets
`MasterBudget!F` (Variance Amount)
Google Sheets (computed)
`MasterBudget!F` / `MasterBudget!E`
Google Sheets
`MasterBudget!G` (Variance Pct)
Google Sheets (CONFIG)
`CONFIG!B3` (variance_threshold)
Google Sheets
`MasterBudget!H` (Flag: TRUE if Variance Pct > threshold)
Agent 3 handoff: MasterBudget to DocuSign and Google Drive (Approval Routing Agent)
Source tool
Source field
Destination tool
Destination field
Google Sheets
`MasterBudget!I` (Finance Cleared = TRUE)
DocuSign
Envelope creation trigger condition
Google Sheets
`CONFIG!B1` (cycle_name)
DocuSign
`envelopeDefinition.emailSubject` (Budget Approval Required: {cycle_name})
Google Sheets (generated PDF)
MasterBudget summary export
DocuSign
`documents[0].documentBase64`
Credential store
`DOCUSIGN_SIGNERS` array
DocuSign
`recipients.signers[]` (name, email, routingOrder)
DocuSign (Connect event)
`event.status`
Google Sheets
`MasterBudget` archive log: approval status
DocuSign (Connect event)
`event.completedDateTime`
Google Sheets
`MasterBudget` archive log: completion timestamp
DocuSign (download)
Signed PDF binary
Google Drive
Multipart upload body
Google Sheets
`CONFIG!B1` (cycle_name)
Google Drive
Sub-folder name: '{cycle_name} Signed Budget'
Google Drive
`file.webViewLink`
Slack
`chat.postMessage.text` archive URL
Google Drive
`file.webViewLink`
Google Sheets
`MasterBudget` archive log: drive URL
Integration and API SpecPage 3 of 4
FS-DOC-05Technical
04Build stack and orchestration
Orchestration layout
Three discrete workflows, one per agent. Each workflow is self-contained with its own trigger, error handler, and retry configuration. Shared state is maintained exclusively via the Google Sheets master workbook (GSHEETS_MASTER_ID). No direct workflow-to-workflow calls; Agent 2 and Agent 3 are each triggered by a state change written to the Sheet by the preceding agent or by an inbound webhook event.
Credential store
All credentials and configuration values are stored in the orchestration platform's native encrypted credential store. No credential or environment-specific ID is hardcoded in any workflow step. Workflows reference credentials by the key names defined in the credential store (see code block below).
Agent 1 trigger (Submission Coordinator)
Poll-based. The workflow polls the SubmissionTracker tab every 30 minutes during active budget cycles. The active cycle flag is read from CONFIG!B6 (active_cycle: TRUE/FALSE). When the computed time delta between now and CONFIG!B2 falls below 48 hours or 24 hours, and the corresponding reminder flag in SubmissionTracker!E or !F is FALSE, the reminder DM is dispatched and the flag is set to TRUE. No inbound webhook required.
Agent 2 trigger (Budget Consolidation)
Webhook-based. An Apps Script on-edit trigger in the master Sheet detects when all SubmissionTracker!B values equal 'Submitted', or when the current timestamp passes CONFIG!B2 and at least one submission exists. The Apps Script POSTs a JSON payload to the orchestration layer's Agent 2 inbound webhook endpoint. The endpoint must be HTTPS with a shared secret header (X-FullSpec-Secret: {AGENT2_WEBHOOK_SECRET}) validated before processing.
Agent 3 trigger (Approval Routing)
Webhook-based (dual source). The workflow is triggered in two cases: (1) an Apps Script on-edit trigger fires when MasterBudget!I for all rows is set to TRUE by the finance manager, POSTing to the Agent 3 inbound webhook endpoint with the same shared secret pattern; (2) the DocuSign Connect webhook POSTs envelope status events (completed, declined, voided) to the same endpoint. The workflow inspects the payload source and routes to the appropriate branch: envelope creation branch or envelope result handling branch.
DocuSign Connect signature validation
All inbound DocuSign Connect payloads must be validated using HMAC-SHA256. The raw request body is hashed with DOCUSIGN_CONNECT_HMAC_SECRET and compared to the X-DocuSign-Signature-1 header value. Requests failing validation are rejected with HTTP 400 and logged.
Apps Script webhook secret validation
All inbound Apps Script POST payloads must include the header X-FullSpec-Secret with the value matching AGENT2_WEBHOOK_SECRET or AGENT3_WEBHOOK_SECRET respectively. Requests without a valid secret are rejected with HTTP 401.
Credential store — all values must be populated before any workflow is activated
// Credential store contents (all keys stored as encrypted secrets)
// Google Workspace (service account)
GOOGLE_SA_KEY = {service account JSON key, full content}
GSHEETS_MASTER_ID = {Google Sheets workbook ID string}
GDRIVE_ARCHIVE_FOLDER_ID = {Google Drive parent folder ID string}
GFORMS_BUDGET_FORM_ID = {Google Forms form ID string}
GFORMS_ENTRY_DEPT = {pre-fill entry ID for Department Name field}
GFORMS_ENTRY_ACTUALS = {pre-fill entry ID for Prior Actuals field}
// Xero
XERO_CLIENT_ID = {OAuth app client ID}
XERO_CLIENT_SECRET = {OAuth app client secret}
XERO_ACCESS_TOKEN = {current access token, refreshed by workflow}
XERO_REFRESH_TOKEN = {current refresh token, updated on each refresh}
XERO_TENANT_ID = {connected Xero organisation tenant ID}
XERO_TRACKING_ID = {tracking category ID for cost centre mapping}
// Slack
SLACK_BOT_TOKEN = xoxb-{workspace bot token}
// DocuSign
DOCUSIGN_INTEGRATION_KEY = {DocuSign app integration key (client ID)}
DOCUSIGN_RSA_PRIVATE_KEY = {RSA private key PEM for JWT grant flow}
DOCUSIGN_ACCOUNT_ID = {DocuSign account GUID}
DOCUSIGN_BASE_URI = https://{subdomain}.docusign.net
DOCUSIGN_TEMPLATE_ID = {envelope template ID, if using pre-built template}
DOCUSIGN_SIGNERS = [{name, email, routingOrder} JSON array]
DOCUSIGN_CONNECT_HMAC_SECRET = {Connect webhook HMAC shared secret}
// Orchestration layer webhook secrets
AGENT2_WEBHOOK_SECRET = {shared secret for Agent 2 inbound webhook}
AGENT3_WEBHOOK_SECRET = {shared secret for Agent 3 inbound webhook}The XERO_ACCESS_TOKEN and XERO_REFRESH_TOKEN entries must be updated by the workflow on every successful token refresh. The orchestration platform's credential store must support write-back for these two keys. If the platform does not support credential write-back natively, store the tokens in a dedicated locked CONFIG tab row in the master Sheet and treat that row as the live token store, reading and writing via the Sheets API.
05Error handling and retry logic
Every integration point has a defined failure behaviour. Unhandled exceptions must never fail silently. All errors must be logged to the orchestration platform's execution log and, where marked below, must trigger an alert to the finance manager via Slack DM using CONFIG!B4.
Integration
Scenario
Required behaviour
Google Sheets (all agents)
API returns 429 Too Many Requests
Retry with exponential backoff: wait 2s, 4s, 8s (max 3 retries). If all retries fail, log the error and alert finance manager via Slack. Pause the workflow run; do not skip the failed step.
Google Sheets (Agent 1 poll)
GSHEETS_MASTER_ID workbook is inaccessible or returns 403
Log the error with timestamp. Alert finance manager via Slack: 'Budget tracker unreachable, manual check required.' Retry once after 10 minutes. If still failing, halt Agent 1 polling until manually restarted.
Google Forms (Agent 2)
FormResponses tab contains a row with missing mandatory fields (Department, Category, or Amount)
Flag the row in SubmissionTracker!B as 'Validation Failed'. Do not include the row in the MasterBudget consolidation. Post a Slack DM to the relevant department head (via SubmissionTracker!G) requesting resubmission. Proceed with consolidation for all valid rows.
Xero API (Agent 2)
401 Unauthorized (access token expired)
Immediately attempt token refresh using XERO_REFRESH_TOKEN. On success, update token store and retry the original call once. On refresh failure, log error, alert finance manager via Slack: 'Xero token refresh failed, actuals pull incomplete.' Proceed with consolidation using blank Prior Actuals column and flag all rows with missing actuals.
Xero API (Agent 2)
API returns 503 or timeout on actuals pull
Retry with backoff: 5s, 15s, 30s (max 3 retries). If all retries fail, continue consolidation with blank Prior Actuals and set MasterBudget!H (Flag) = TRUE for all rows to force finance review. Log the failure and alert finance manager.
Xero API (Agent 2)
Cost category in form response does not match any Xero tracking category label
Write the unmatched row to MasterBudget with a note in MasterBudget!C: '[UNMAPPED CATEGORY]'. Set Flag = TRUE. Do not block the consolidation run. Alert finance manager via Slack listing unmapped categories for manual reconciliation.
Slack (Agent 1 and Agent 3)
Slack API returns 404 for a department head user ID
Fall back immediately to posting the reminder or notification in the finance Slack channel (CONFIG!B5) mentioning the department name explicitly. Log the failed user ID. Do not retry the DM to the invalid user ID without first resolving the ID manually.
Slack (Agent 1 and Agent 3)
Slack API returns 429 or 503
Retry with exponential backoff: 2s, 6s, 20s (max 3 retries). If all retries fail, log the failure. The reminder or notification is considered non-critical; do not halt the workflow. Record the unsent message in the execution log for manual follow-up.
DocuSign (Agent 3)
Envelope creation returns 400 or 401
On 401: attempt JWT token refresh and retry once. On 400: log the full error payload, alert finance manager via Slack: 'DocuSign envelope creation failed, manual upload required.' Halt the Agent 3 envelope branch and do not proceed to archiving.
DocuSign Connect (Agent 3)
Inbound webhook payload fails HMAC signature validation
Reject the request with HTTP 400. Log the source IP and raw payload. Do not process the envelope status update. Alert the FullSpec team via support@gofullspec.com if more than 3 failed validation attempts occur within one hour.
DocuSign (Agent 3)
Envelope status event returns 'declined' or 'voided'
Do not proceed to Google Drive archiving. Alert finance manager via Slack DM: 'DocuSign envelope {envelopeId} was {declined/voided}. Manual review and resubmission required.' Write status to MasterBudget archive log. Halt the Agent 3 workflow run.
Google Drive (Agent 3)
Signed PDF upload fails (403, 500, or timeout)
Retain the downloaded PDF in the orchestration platform's temporary file store. Retry the upload after 60 seconds (max 3 retries). If all retries fail, alert finance manager via Slack with the error and instruct manual upload. Log the temp file location. Do not post the Slack completion notification until the upload succeeds.
All workflow execution logs must be retained for a minimum of 90 days. For any error that results in a halted workflow run, the FullSpec team will conduct a root-cause review within one business day of the alert being raised. Contact support@gofullspec.com for any escalation outside of normal error-handling bounds.
Integration and API SpecPage 4 of 4