Back to Client Deposit & Payment Tracking

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

Client Deposit and Payment Tracking

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

This document provides the complete integration and API specification for the three-agent Client Deposit and Payment Tracking automation. It covers every tool connected in the flow, exact authentication requirements, required OAuth scopes, webhook and trigger configuration, field mappings across agent handoffs, orchestration layout, credential store contents, and defined error handling behaviour for every integration point. This document is intended for the FullSpec build team. [YourCompany.com] is not expected to action anything in this document directly, but should ensure all tool access and API credentials are confirmed before the build begins.

01Tool inventory

Tool
Role in automation
Auth method
Min plan required
Used by agent(s)
Xero
Invoice creation trigger and payment reconciliation
OAuth 2.0 (3-legged)
Starter or above
Agent 1, Agent 3
Stripe
Inbound payment detection and matching
API key (secret key)
Standard (free tier sufficient)
Agent 1
Gmail
Outbound chaser and confirmation emails
OAuth 2.0 (Google Workspace)
Google Workspace or free Gmail with OAuth
Agent 2
HubSpot
Client activity logging for all outbound email events
OAuth 2.0 or Private App token
Free CRM or above (API access required)
Agent 2
Google Sheets
Central payment tracker: single source of truth
OAuth 2.0 (Google Workspace)
Any Google account with Sheets access
Agent 1, Agent 2
Slack
Internal payment cleared notification to project channel
OAuth 2.0 (Bot token)
Free or above
Agent 3
Automation platform (orchestration layer)
Workflow orchestration, credential store, scheduling, and retry logic
Platform-native credential management
N/A: internal build tooling
All agents
Before you connect anything: sandbox-test all connections using non-production credentials before pointing any integration at live Xero data, real client email addresses, or the active Slack channel. Use Xero demo company, Stripe test mode, a Gmail alias, a HubSpot sandbox or test contact, a throwaway Google Sheet, and a private Slack channel for all pre-production validation.

02Per-tool integration detail

Xero

Used by Agent 1 (Deposit Monitor Agent) to detect new invoices with deposit terms and to apply reconciled payments. Used by Agent 3 (Internal Notification Agent) to confirm full settlement status.

Auth method
OAuth 2.0 (3-legged authorization code flow). The authorizing user must be a Xero organization admin or have invoice and bank transaction permissions. Access tokens expire after 30 minutes; refresh tokens are valid for 60 days and must be stored in the credential store and rotated automatically by the orchestration layer.
Required scopes
openid profile email accounting.transactions accounting.contacts.read accounting.settings.read offline_access
Webhook / trigger setup
Register a webhook endpoint in the Xero Developer Portal under the connected app. Subscribe to the event type: invoice.created and invoice.updated. Xero signs each payload with an HMAC-SHA256 signature using the webhook key stored in the credential store. The orchestration layer must validate the X-Xero-Signature header on every inbound request before processing. Reject and log any request where signature validation fails.
Required configuration
Xero tenant ID stored in credential store (not hardcoded). Invoice filter: only process invoices where Type=ACCREC and Status=AUTHORISED and a line item or reference field contains the deposit term pattern configured at build time (e.g. 'deposit', 'Deposit Due'). The deposit amount field and due date field used by [YourCompany.com] must be confirmed during discovery and stored as config variables.
Rate limits
Xero enforces a limit of 60 API calls per minute per connected app and 5,000 calls per day. At ~60 invoices per month and a daily polling reconciliation job, estimated daily call volume is well under 200. Throttling is not required at current volume, but the orchestration layer must handle HTTP 429 responses with exponential backoff (starting at 5 seconds, max 3 retries).
Constraints
Xero does not support bulk reconciliation via API in a single call; each payment must be applied to its invoice individually. The Xero demo company environment must be used for all pre-production testing. Multi-currency invoices are out of scope for the Standard build.
// Inbound webhook payload (invoice.created)
InvoiceID: string (UUID)
Contact.ContactID: string (UUID)
Contact.Name: string
AmountDue: decimal
DueDate: date (YYYY-MM-DD)
Reference: string
Status: string
// Outbound: POST /Payments
InvoiceID: string
Account.Code: string (bank account code from config)
Date: date
Amount: decimal
Stripe

Used by Agent 1 (Deposit Monitor Agent) to poll for incoming payments and match them to open deposit records by amount, client reference, and date range.

Auth method
API key authentication using the Stripe secret key (sk_live_...). The secret key must be stored in the credential store and never written to logs, code, or configuration files. Use the Stripe restricted key with read-only permissions on charges and payment intents.
Required scopes
Restricted key permissions: read on charges, read on payment_intents, read on customers. No write access to Stripe is required for this build.
Webhook / trigger setup
No inbound Stripe webhook is used in the Standard build. Agent 1 polls the Stripe charges or payment intents list endpoint on a daily schedule (recommended: 08:00 local time). Poll window: created timestamp between (today minus 2 days) and now, to account for timezone drift and processing delays. Matching logic: compare charge.amount (in cents) to the expected deposit amount, and charge.metadata.invoice_ref or charge.description to the Xero invoice reference.
Required configuration
Stripe account ID stored in credential store. Polling schedule stored as a config variable (default: daily at 08:00). Matching tolerance window stored as config (default: plus or minus 0 cents for exact match; flag for manual review otherwise). Metadata key name used by [YourCompany.com] for invoice references confirmed during discovery and stored as a config variable.
Rate limits
Stripe enforces 100 read requests per second in live mode. A single daily poll fetching up to 100 charges uses fewer than 5 requests. No throttling needed at current volume. The orchestration layer should handle HTTP 429 with a 10-second backoff and retry up to 3 times.
Constraints
Partial payments, split payments, and payments with missing or mismatched metadata cannot be auto-matched and must be flagged to the Google Sheets tracker with status='REVIEW_REQUIRED' for bookkeeper action. Stripe test mode (sk_test_...) must be used for all pre-production testing.
// Polled from GET /v1/charges or GET /v1/payment_intents
id: string (charge or payment intent ID)
amount: integer (cents)
currency: string
status: string (succeeded | pending | failed)
metadata.invoice_ref: string
description: string
created: unix timestamp
customer: string (Stripe customer ID)
// Passed to Agent 1 matching logic
matched_invoice_id: string (Xero InvoiceID)
match_confidence: string (EXACT | PARTIAL | NONE)
Gmail

Used by Agent 2 (Client Communication Agent) to send overdue deposit chasers, deposit receipt confirmations, and final payment reminders to clients.

Auth method
OAuth 2.0 (3-legged) using a dedicated sending account. The authorizing Google account should be the business email address used for client billing communications. Access token and refresh token stored in the credential store. Refresh tokens do not expire for Google Workspace accounts with offline_access granted.
Required scopes
https://www.googleapis.com/auth/gmail.send https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/gmail.compose
Webhook / trigger setup
No Gmail webhook is used. Agent 2 is triggered by an internal event from Agent 1 (overdue flag or payment match confirmation). Gmail is used purely as an outbound sending channel via the Gmail API messages.send endpoint.
Required configuration
Three email template IDs (or template text blocks) stored in the credential store: CHASER_TEMPLATE, CONFIRMATION_TEMPLATE, FINAL_REMINDER_TEMPLATE. Each template must include placeholders: {{client_name}}, {{invoice_ref}}, {{deposit_amount}}, {{due_date}}, {{remaining_balance}}, {{payment_link}}. Sender display name and reply-to address stored as config variables. Chaser schedule (e.g. Day 1, Day 4, Day 7 after due date) stored as config. Duplicate-send prevention: before sending, Agent 2 checks the Google Sheets tracker column email_last_sent_date; a chaser is not sent if one was sent within the configured minimum interval (default: 48 hours).
Rate limits
Gmail API enforces 250 quota units per user per second and a daily sending limit of 2,000 messages for Google Workspace. At ~60 invoices per month with up to 3 chasers each, maximum monthly send volume is under 200 emails. No throttling needed. Handle HTTP 429 with 5-second backoff and 3 retries.
Constraints
The Gmail API does not support scheduling future sends natively; the orchestration layer scheduler handles send timing. All emails must be sent from the authenticated account only. BCC to an internal audit address should be configured as a config variable if required.
// Input from Agent 1 via Google Sheets row
client_email: string
client_name: string
invoice_ref: string
deposit_amount: decimal
due_date: date
remaining_balance: decimal
payment_link: string
email_type: string (CHASER | CONFIRMATION | FINAL_REMINDER)
// Output: Gmail API messages.send
to: client_email
subject: rendered from template
body: rendered from template with substituted placeholders
// Written back to Google Sheets
email_last_sent_date: date
email_type_last_sent: string
HubSpot

Used by Agent 2 (Client Communication Agent) to log every outbound chaser and confirmation email as a contact activity against the matching client record.

Auth method
Private App token (recommended over OAuth for server-to-server automation). Generate a Private App in HubSpot Settings under Integrations. Token stored in the credential store. Alternatively, OAuth 2.0 with a connected app if [YourCompany.com] requires centralized token management.
Required scopes
crm.objects.contacts.read crm.objects.contacts.write crm.objects.deals.read timeline.events.write crm.lists.read
Webhook / trigger setup
No HubSpot webhook is used in this build. HubSpot is written to after each Gmail send event. Agent 2 creates a timeline event or engagement (type: EMAIL) on the matching contact record using the HubSpot Engagements v2 API or CRM Timeline Events API.
Required configuration
HubSpot portal ID stored in the credential store. Contact lookup strategy: match by contact email address first; fall back to contact name if no email match found. If no match is found, the activity is written to a holding log in Google Sheets with status='HUBSPOT_MATCH_FAILED' for manual review. HubSpot contact property used to store Xero client name must be confirmed during discovery (commonly firstname + lastname or company). Timeline event type ID created during onboarding and stored as a config variable.
Rate limits
HubSpot enforces 110 requests per 10 seconds and 40,000 requests per day on the free plan. At fewer than 200 activities per month, rate limiting is not a concern. Handle HTTP 429 with 10-second backoff and 3 retries.
Constraints
HubSpot contact records must have email addresses that match the client email addresses in Xero. A one-off data alignment between Xero contacts and HubSpot contacts is required before go-live. The Private App token must be rotated annually and the new value updated in the credential store.
// Input from Agent 2 post-send
contact_email: string
contact_name: string
activity_type: string (EMAIL)
email_subject: string
email_body_summary: string
activity_date: datetime (ISO 8601)
invoice_ref: string
outstanding_amount: decimal
// HubSpot API call: POST /crm/v3/objects/engagements or
// POST /crm/v3/timeline/events
portalId: integer (from credential store)
contactId: string (resolved from contact_email lookup)
timestamp: unix milliseconds
properties.hs_activity_type: EMAIL
properties.hs_body_preview: email_body_summary
Integration and API SpecPage 1 of 3
FS-DOC-05Technical
Google Sheets

Used by Agent 1 (Deposit Monitor Agent) as the central payment tracker and by Agent 2 (Client Communication Agent) to read client data and write email send records.

Auth method
OAuth 2.0 (same Google account as Gmail, or a dedicated service account with the sheet shared to the service account email). Service account JSON key stored in the credential store. Using a service account is preferred for server-to-server access as it does not require user re-authorization.
Required scopes
https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive.file
Webhook / trigger setup
No native Sheets webhook is used. Agent 1 writes new rows on invoice creation and updates rows on payment detection. Agent 2 reads rows to determine chaser eligibility and writes email send timestamps back. All reads and writes use the Sheets API v4 spreadsheets.values.get and spreadsheets.values.update methods.
Required configuration
Spreadsheet ID stored in the credential store (not hardcoded). Sheet tab name stored as a config variable (default: 'PaymentTracker'). Required column structure (A through M, confirmed at build time): A=invoice_ref, B=client_name, C=client_email, D=deposit_amount_due, E=deposit_due_date, F=stripe_payment_id, G=amount_received, H=payment_matched_date, I=status, J=email_last_sent_date, K=email_type_last_sent, L=remaining_balance, M=notes. Header row must exist in row 1. New invoice rows appended below the last used row. Status column I valid values: PENDING, MATCHED, REVIEW_REQUIRED, CONFIRMED, SETTLED.
Rate limits
Google Sheets API enforces 300 read and 300 write requests per minute per project. At 60 invoices per month with a daily poll, estimated daily requests are under 50. No throttling required. Handle HTTP 429 with 5-second backoff and 3 retries.
Constraints
The spreadsheet must not be moved or renamed after the Spreadsheet ID is stored. If the sheet structure changes (columns added or reordered), the field mapping config must be updated before the next run. Do not use merged cells or frozen rows beyond row 1 in the PaymentTracker tab.
// Agent 1 writes on invoice.created (append row)
A: invoice_ref (string)
B: client_name (string)
C: client_email (string)
D: deposit_amount_due (decimal)
E: deposit_due_date (date YYYY-MM-DD)
I: status = 'PENDING'
// Agent 1 updates on Stripe match (update row by invoice_ref)
F: stripe_payment_id (string)
G: amount_received (decimal)
H: payment_matched_date (date)
I: status = 'MATCHED' | 'REVIEW_REQUIRED'
L: remaining_balance (decimal)
// Agent 2 reads columns A-L to determine chaser eligibility
// Agent 2 writes after send
J: email_last_sent_date (date)
K: email_type_last_sent (string)
Slack

Used by Agent 3 (Internal Notification Agent) to post a payment cleared alert to the designated project channel when full invoice settlement is confirmed in Xero.

Auth method
OAuth 2.0 Bot token (xoxb-...). Install a Slack app to the workspace with bot token scopes. The bot token is stored in the credential store. The bot must be invited to the target channel before it can post.
Required scopes
chat:write chat:write.public channels:read groups:read
Webhook / trigger setup
Agent 3 uses the Slack Web API chat.postMessage method. No inbound Slack webhook or event subscription is required. The trigger for Agent 3 is an internal event from Agent 1 when Xero invoice status is updated to PAID and the Google Sheets row status is updated to 'SETTLED'.
Required configuration
Target Slack channel ID stored in the credential store (use channel ID, not channel name, to prevent breakage if the channel is renamed). Slack app bot token stored in the credential store. Message format template stored as a config variable. Recommended message format: 'Payment cleared: {{client_name}} (Invoice {{invoice_ref}}) has settled in full. Amount: ${{cleared_amount}}. Xero updated.'
Rate limits
Slack Web API enforces a rate limit of approximately 1 message per second per channel per app (Tier 3 method). At ~60 settlement events per month, this is negligible. Handle HTTP 429 with a 1-second backoff and 3 retries.
Constraints
The Slack bot must be a member of the target channel. If the channel is private, the bot must be explicitly invited. Do not post client payment amounts or email addresses in public Slack channels. Confirm channel privacy settings with [YourCompany.com] before go-live.
// Input from Agent 3 trigger (Xero PAID event + Sheets SETTLED status)
client_name: string
invoice_ref: string
cleared_amount: decimal
settlement_date: date
// Slack API: POST /api/chat.postMessage
channel: string (channel ID from credential store)
text: string (rendered message from template)
username: string (bot display name from config)
icon_emoji: string (optional, e.g. ':white_check_mark:')

03Field mappings between tools

The tables below define the exact field mappings for each agent handoff in the automation flow. Use monospace field names exactly as listed. Any field name mismatch between a source API response and the destination write call will cause a silent data gap in the tracker.

Handoff 1: Xero to Google Sheets (Agent 1, on invoice.created webhook). This is the first write to the payment tracker and must execute before any polling or email logic runs.
Source tool
Source field
Destination tool
Destination field
Xero
InvoiceID
Google Sheets
A: invoice_ref
Xero
Contact.Name
Google Sheets
B: client_name
Xero
Contact.EmailAddress
Google Sheets
C: client_email
Xero
AmountDue
Google Sheets
D: deposit_amount_due
Xero
DueDate
Google Sheets
E: deposit_due_date
System
(hardcoded at write time)
Google Sheets
I: status = 'PENDING'
Handoff 2: Stripe to Google Sheets (Agent 1, on daily poll match). Updates an existing row identified by matching invoice_ref to Xero InvoiceID in column A.
Source tool
Source field
Destination tool
Destination field
Stripe
id
Google Sheets
F: stripe_payment_id
Stripe
amount (divided by 100 for dollars)
Google Sheets
G: amount_received
System
(date of successful poll match)
Google Sheets
H: payment_matched_date
System
MATCHED | REVIEW_REQUIRED | PARTIAL
Google Sheets
I: status
Calculated
deposit_amount_due minus amount_received
Google Sheets
L: remaining_balance
Handoff 3: Google Sheets to Gmail (Agent 2, on overdue flag or match confirmation). Agent 2 reads the tracker row and substitutes values into the email template before sending.
Source tool
Source field
Destination tool
Destination field
Google Sheets
C: client_email
Gmail
to (recipient address)
Google Sheets
B: client_name
Gmail
template placeholder: {{client_name}}
Google Sheets
A: invoice_ref
Gmail
template placeholder: {{invoice_ref}}
Google Sheets
D: deposit_amount_due
Gmail
template placeholder: {{deposit_amount}}
Google Sheets
E: deposit_due_date
Gmail
template placeholder: {{due_date}}
Google Sheets
L: remaining_balance
Gmail
template placeholder: {{remaining_balance}}
Config
payment_link (from config variable)
Gmail
template placeholder: {{payment_link}}
Handoff 4: Gmail send event to HubSpot (Agent 2, immediately after successful Gmail send). Uses the client_email to resolve the HubSpot contact before writing the engagement.
Source tool
Source field
Destination tool
Destination field
Gmail
to (recipient address)
HubSpot
contact lookup key: email
Gmail
subject (rendered)
HubSpot
engagement.metadata.subject
Gmail
body preview (first 500 chars)
HubSpot
engagement.metadata.body (preview)
System
(timestamp of send)
HubSpot
engagement.timestamp
Google Sheets
A: invoice_ref
HubSpot
engagement.metadata.body (appended as note)
Google Sheets
D: deposit_amount_due
HubSpot
engagement.metadata.body (appended as note)
Handoff 5: Xero PAID event to Slack (Agent 3, on invoice fully settled). Agent 3 reads the Google Sheets row for remaining_balance confirmation before posting.
Source tool
Source field
Destination tool
Destination field
Xero
Contact.Name
Slack
message template: {{client_name}}
Xero
InvoiceID
Slack
message template: {{invoice_ref}}
Xero
AmountPaid
Slack
message template: {{cleared_amount}}
System
(date of Xero PAID confirmation)
Slack
message template: {{settlement_date}}
Config
channel ID (from credential store)
Slack
channel parameter in chat.postMessage
Integration and API SpecPage 2 of 3
FS-DOC-05Technical

04Build stack and orchestration

Orchestration layout
One workflow per agent: three workflows total. Workflow 1 = Deposit Monitor Agent (webhook trigger from Xero, daily Stripe poll sub-workflow). Workflow 2 = Client Communication Agent (event trigger from Workflow 1 output). Workflow 3 = Internal Notification Agent (event trigger from Workflow 1 on SETTLED status). All three workflows share a single credential store; no credentials are embedded in workflow configuration.
Agent 1 trigger mechanism
Webhook (push). Xero posts a signed invoice.created or invoice.updated event to the orchestration layer's inbound webhook URL. The webhook URL is registered in the Xero Developer Portal. Signature validation: HMAC-SHA256 using the webhook key from the credential store. All requests with invalid signatures are rejected with HTTP 401 and logged. Stripe polling is a scheduled sub-workflow within Agent 1, running daily at 08:00. Poll window: last 48 hours of Stripe charges with status=succeeded.
Agent 2 trigger mechanism
Internal event (poll on shared state). Agent 2 polls the Google Sheets PaymentTracker at 08:30 daily (30 minutes after Agent 1 Stripe poll completes). It reads all rows where status is PENDING and deposit_due_date is past the current date (overdue), or where status has just changed to MATCHED. Duplicate-send prevention is enforced by checking email_last_sent_date before any send action.
Agent 3 trigger mechanism
Internal event (webhook from Agent 1). When Agent 1 successfully reconciles a full payment in Xero and updates the Sheets row to SETTLED, it emits an internal event consumed by Agent 3. Agent 3 does not poll; it is event-driven only. No signature validation is required for internal events, but the event payload must include the Xero InvoiceID for Agent 3 to look up confirmation data.
Credential store
All secrets, tokens, IDs, and config variables are stored in the automation platform's native encrypted credential store. Nothing is hardcoded in workflow steps or configuration files. Credential references use named keys as listed in the code block below.
Credential store key manifest: all values must be populated before any workflow is activated
// Credential store contents (key: description)

XERO_CLIENT_ID          : OAuth 2.0 app client ID (Xero Developer Portal)
XERO_CLIENT_SECRET      : OAuth 2.0 app client secret
XERO_REFRESH_TOKEN      : stored refresh token, rotated every 55 days
XERO_TENANT_ID          : Xero organization tenant UUID
XERO_WEBHOOK_KEY        : HMAC-SHA256 signing key from Xero Developer Portal

STRIPE_SECRET_KEY       : sk_live_... (restricted: charges.read, payment_intents.read, customers.read)
STRIPE_POLL_WINDOW_HOURS: 48 (config: hours lookback for daily Stripe poll)
STRIPE_MATCH_METADATA_KEY: invoice_ref (config: Stripe metadata key for invoice reference)

GMAIL_CLIENT_ID         : OAuth 2.0 client ID (Google Cloud Console)
GMAIL_CLIENT_SECRET     : OAuth 2.0 client secret
GMAIL_REFRESH_TOKEN     : stored refresh token for sending account
GMAIL_FROM_ADDRESS      : billing@[YourCompany.com] (config: sender address)
GMAIL_REPLY_TO          : accounts@[YourCompany.com] (config: reply-to)
GMAIL_BCC_ADDRESS       : audit@[YourCompany.com] (config: optional BCC for audit trail)
GMAIL_CHASER_TEMPLATE   : full text of overdue chaser email template
GMAIL_CONFIRMATION_TEMPLATE: full text of deposit confirmation email template
GMAIL_FINAL_REMINDER_TEMPLATE: full text of final payment reminder template
GMAIL_CHASER_SCHEDULE_DAYS: [1,4,7] (config: days after due date to send chasers)
GMAIL_MIN_INTERVAL_HOURS: 48 (config: minimum hours between chasers to same client)

HUBSPOT_PRIVATE_APP_TOKEN: pat-... (Private App token with CRM and timeline scopes)
HUBSPOT_PORTAL_ID       : integer (HubSpot account portal ID)
HUBSPOT_TIMELINE_EVENT_TYPE_ID: string (created during onboarding)
HUBSPOT_CONTACT_LOOKUP_FALLBACK: name (config: fallback lookup field if email not found)

GSHEETS_SERVICE_ACCOUNT_JSON: full JSON key for Google service account
GSHEETS_SPREADSHEET_ID  : spreadsheet ID from URL of PaymentTracker sheet
GSHEETS_TAB_NAME        : PaymentTracker (config: sheet tab name)

SLACK_BOT_TOKEN         : xoxb-... (Bot token with chat:write scope)
SLACK_CHANNEL_ID        : C0XXXXXXXXX (target project channel ID)
SLACK_MESSAGE_TEMPLATE  : 'Payment cleared: {{client_name}} (Invoice {{invoice_ref}}) settled in full. Amount: ${{cleared_amount}}. Xero updated.'

PAYMENT_LINK_BASE_URL   : https://pay.[YourCompany.com]/ (config: base URL for payment links in chasers)

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 layer's error log with: timestamp, workflow name, step name, error type, HTTP status code (where applicable), and the payload that caused the failure. Where a retry limit is reached, an alert must be sent to support@gofullspec.com and the relevant row in the Google Sheets tracker must be updated with status='ERROR' and a note in column M.

Integration
Scenario
Required behaviour
Xero webhook inbound
Signature validation fails (invalid or missing X-Xero-Signature)
Reject with HTTP 401. Log the raw payload and headers. Do not process. No retry. Alert the FullSpec monitoring channel.
Xero webhook inbound
Xero delivers a duplicate webhook for the same InvoiceID
Check Google Sheets for an existing row with matching invoice_ref before processing. If row exists and status is not PENDING, discard the event and log as 'duplicate_skipped'.
Xero API: POST /Payments (reconcile deposit)
HTTP 429 rate limit exceeded
Exponential backoff: wait 5 s, 15 s, 45 s. Retry up to 3 times. If all retries fail, set Sheets row status='ERROR', note='Xero reconcile failed: rate limit', and alert support@gofullspec.com.
Xero API: POST /Payments (reconcile deposit)
HTTP 400 or 409 (invoice already reconciled or invalid state)
Do not retry. Log the full error response. Set Sheets row status='REVIEW_REQUIRED', note='Xero reconcile error: see log'. Alert support@gofullspec.com. Bookkeeper must resolve manually.
Stripe daily poll
Stripe API returns HTTP 500 or connection timeout
Retry after 10 s, then 30 s, then 60 s (3 attempts). If all fail, skip this poll cycle and log 'Stripe poll failed: will retry next scheduled run'. Do not send chasers based on stale match data from a failed poll.
Stripe payment matching
No matching payment found for an invoice past its due date
Set Sheets row status='PENDING' (unchanged). Agent 2 will evaluate the row against the chaser schedule and send an overdue chaser if the due date has passed and the minimum chaser interval has elapsed.
Stripe payment matching
Partial or misreferenced payment found (amount mismatch or metadata missing)
Set Sheets row status='REVIEW_REQUIRED'. Note the Stripe charge ID and received amount in column M. Do not send a confirmation email. Do not reconcile in Xero. Alert the bookkeeper via a Slack message to the same project channel with prefix '[ACTION REQUIRED]'.
Gmail API: messages.send
HTTP 429 quota exceeded or HTTP 500 server error
Retry after 5 s, 15 s, 45 s (3 attempts). If all fail, log the failure, do not update email_last_sent_date in Sheets (so the next Agent 2 run will attempt to send again), and alert support@gofullspec.com.
Gmail API: messages.send
Duplicate-send prevention check: email_last_sent_date is within GMAIL_MIN_INTERVAL_HOURS
Skip send. Log 'chaser_skipped: minimum interval not elapsed'. Do not update email_last_sent_date. No alert needed. Normal behaviour.
HubSpot API: engagement or timeline event write
Contact not found by email lookup or name fallback
Do not fail the Gmail send. Write the activity to a holding log in a second Google Sheets tab ('HubSpot_Failures') with client_email, invoice_ref, email_type, and timestamp. Flag for manual HubSpot entry. Alert support@gofullspec.com once per day if the holding log has new rows.
Google Sheets API: read or write
HTTP 429 or HTTP 500
Retry after 5 s, 15 s, 45 s (3 attempts). If all fail, halt the current workflow run and log 'Sheets unavailable: workflow halted'. Do not proceed to email send or Xero reconcile steps without a confirmed Sheets write. Alert support@gofullspec.com.
Slack API: chat.postMessage
HTTP 429 rate limit or channel not found
Retry after 1 s, 3 s, 9 s (3 attempts). If all fail, log the failure and send a fallback email to the address in GMAIL_FROM_ADDRESS with the same payment cleared message. Do not fail silently. Alert support@gofullspec.com.
General rule: no workflow step may complete in a success state without having written a confirmed record to Google Sheets. If the Sheets write fails, the entire step is considered failed regardless of whether an email was sent or a Slack message was posted. This ensures the tracker remains the authoritative source of truth for all reconciliation and audit purposes.
Integration and API SpecPage 3 of 3

More documents for this process

Every document generated for Client Deposit & Payment Tracking.

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