FS-DOC-04Technical
Developer Handover Pack
Receivables & Invoice Chasing
Process
Receivables & Invoice Chasing
Build option
Standard (recommended)
Total build effort
56 hours across 4 weeks
Monthly tooling cost
$145/month
Volume
~120 invoices/month, ~318 automation runs/month
01Process snapshot
The table below maps the seven current-state manual steps against owner, tool, time cost, and bottleneck flag. Three steps are flagged as primary bottlenecks: deciding who to chase, writing reminders by hand, and matching payments manually. Together they account for the majority of the 9 hours lost each week. The automation eliminates or replaces steps 1, 2, 3, 4, and 6; steps 5 and 7 remain with a person by design.
Step
Name
Owner
Tool
Time
Bottleneck
Outcome
1
Pull Aged Receivables Report
Bookkeeper
Xero
20 min
No
Automated
2
Decide Who To Chase
Bookkeeper
None
25 min
Yes
Automated
3
Write Reminder Emails
Bookkeeper
Gmail
60 min
Yes
Automated
4
Send And Log Reminders
Bookkeeper
Google Sheets
30 min
No
Automated
5
Watch For Replies
Bookkeeper
Gmail
35 min
No
Remains human
6
Match Incoming Payments
Bookkeeper
Xero
45 min
Yes
Automated
7
Escalate Stubborn Accounts
Practice Manager
None
30 min
No
Remains human
Time cost metric
Before
After
Time on chasing per week
9 hrs/week
2 hrs/week
Annual staff cost
$17,800
$4,000
Avg days to payment
47 days
31 days
Reminders sent on time
62%
100%
Hours saved per week
0
7 hrs/week
Annual saving
0
$13,800/year
Bottleneck summary: Deciding who to chase, hand-writing each reminder, and matching payments by hand are the three steps that swallow the most time and slip first when the team is busy. These map directly to agent build priorities.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical
02Agent specifications
Chase Scheduler Agent
Watches every open invoice in Xero and stages a prioritised reminder sequence based on how overdue each invoice is. Replaces manual steps 1 and 2: pulling the aged receivables report and deciding who to chase. Nothing slips through because the agent evaluates all open balances on a scheduled poll rather than relying on a person to remember.
Trigger
An invoice passes its due date with a balance still owing (Xero webhook or scheduled poll every 15 minutes)
Tools
Xero, FullSpec Automation
Build time
Week 1 to Week 2
Implementation notes
Reminder tone and timing cadence must be agreed with the partners before go-live. Disputed or sensitive account flags in Xero must be respected and excluded from auto-scheduling. Staging rules (e.g. 1 day overdue, 7 days, 14 days, 30 days) should be parameterised so the client can adjust without a code change.
// Input
Xero invoice object {
invoice_id: string,
contact_id: string,
due_date: date,
amount_due: float,
status: 'AUTHORISED' | 'PARTIAL',
days_overdue: integer
}
// Processing
IF days_overdue IN [1, 7, 14, 30] AND account_flagged == false
-> stage reminder at priority tier (LOW | MEDIUM | HIGH | ESCALATE)
-> write scheduled_send_time to FullSpec queue
ELSE
-> skip or log for human review
// Output
Prioritised chase queue entry {
invoice_id: string,
contact_email: string,
reminder_tier: 'LOW' | 'MEDIUM' | 'HIGH' | 'ESCALATE',
scheduled_send_time: ISO8601,
stripe_pay_link: string (generated next stage)
}Reminder Sender Agent
Picks up staged reminders from the queue and sends each one via Gmail with the invoice PDF attached and a Stripe pay link embedded. Logs every send automatically in FullSpec Automation. Replaces manual steps 3 and 4: writing reminder emails by hand and logging sends in a spreadsheet. Email content is templated by reminder tier so tone scales with urgency.
Trigger
A reminder entry in the FullSpec queue reaches its scheduled_send_time
Tools
Gmail, Stripe, FullSpec Automation
Build time
Week 2 to Week 3
Implementation notes
Email templates must be reviewed and approved by the client before activation. Stripe pay link generation uses the Stripe Checkout Sessions API with the invoice amount and currency pre-filled. Gmail must be authorised via OAuth 2.0 with the send scope. Each send event is written to the FullSpec activity log with timestamp, recipient, and tier. If a send fails, the event is retried twice then flagged for human review.
// Input
Queue entry {
invoice_id: string,
contact_email: string,
contact_name: string,
amount_due: float,
currency: string,
reminder_tier: 'LOW' | 'MEDIUM' | 'HIGH' | 'ESCALATE',
invoice_pdf_url: string
}
// Processing
1. Fetch email template for reminder_tier
2. Generate Stripe Checkout Session -> pay_link URL
3. Compose email: merge contact_name, amount_due, pay_link, invoice_pdf_url
4. Gmail.send(to: contact_email, subject, body, attachment: invoice_pdf)
5. Log send event to FullSpec activity log
// Output
Send record {
invoice_id: string,
sent_at: ISO8601,
recipient: string,
reminder_tier: string,
pay_link: string,
send_status: 'success' | 'failed',
retry_count: integer
}Payment Reconciliation Agent
Listens for incoming payments in Xero and matches each one to the correct open invoice, including partial amounts. Marks invoices reconciled, updates their status in Xero, and pushes a team notification via FullSpec Automation. Replaces manual step 6. A short tuning period against real payment data is expected before partial-match confidence stabilises.
Trigger
A payment is detected against an open invoice in Xero (Xero payment webhook or Stripe payment.succeeded event)
Tools
Xero, FullSpec Automation
Build time
Week 3 to Week 4
Implementation notes
Partial payment logic: if amount_paid < amount_due, mark invoice PARTIAL and reschedule a chase reminder for the remaining balance. Full match: mark PAID and remove from chase queue. Unmatched payments are flagged for human review rather than auto-applied. Target auto-match rate is 96% per KPI; residual 4% routes to bookkeeper. Xero reconciliation is performed via the Payments API, not manual bank feed entry.
// Input (Xero payment event or Stripe webhook)
Payment event {
payment_id: string,
invoice_id: string,
amount_paid: float,
currency: string,
payment_date: date,
source: 'stripe' | 'bank_feed' | 'manual'
}
// Processing
IF amount_paid >= amount_due
-> Xero.Payments.create(invoiceID, amount, status: PAID)
-> Remove invoice from chase queue
-> Notify team via FullSpec
ELSE IF amount_paid > 0 AND amount_paid < amount_due
-> Record partial payment in Xero
-> Reschedule chase reminder for remaining balance
-> Notify team of partial receipt
ELSE
-> Flag payment as unmatched -> human review queue
// Output
Reconciliation record {
invoice_id: string,
xero_status: 'PAID' | 'PARTIAL' | 'UNMATCHED',
reconciled_at: ISO8601,
remaining_balance: float,
notification_sent: boolean
}Developer Handover PackPage 2 of 4
FS-DOC-04Technical
03End-to-end data flow
The code block below traces every data state from the overdue invoice trigger through reminder scheduling, email send, payment detection, and final reconciliation. Human handoff points are marked inline.
End-to-end data flow: Invoice overdue trigger to reconciled invoice
// ─── TRIGGER ────────────────────────────────────────────────────────────────
SOURCE: Xero invoice webhook OR scheduled poll (every 15 min)
EVENT: invoice.due_date < today AND invoice.amount_due > 0
invoice.status IN ['AUTHORISED', 'PARTIAL']
// ─── STAGE 1: Chase Scheduler Agent ─────────────────────────────────────────
INPUT: { invoice_id, contact_id, contact_email, contact_name,
due_date, amount_due, currency, days_overdue }
RULE: days_overdue == 1 -> tier = 'LOW', send_delay = +0h
days_overdue == 7 -> tier = 'MEDIUM', send_delay = +0h
days_overdue == 14 -> tier = 'HIGH', send_delay = +0h
days_overdue >= 30 -> tier = 'ESCALATE', send_delay = +0h
account_flagged_sensitive == true -> SKIP, log to human review
WRITE: FullSpec queue entry {
invoice_id, contact_email, contact_name,
reminder_tier, scheduled_send_time, amount_due, currency,
invoice_pdf_url (fetched from Xero Files API)
}
// ─── STAGE 2: Reminder Sender Agent ─────────────────────────────────────────
TRIGGER: queue entry.scheduled_send_time == now()
ACTION 1: Stripe.checkout.sessions.create({
amount: amount_due * 100, // cents
currency: currency,
metadata: { invoice_id }
}) -> pay_link URL
ACTION 2: Load email template for reminder_tier
Merge: { contact_name, amount_due, pay_link, invoice_pdf_url }
ACTION 3: Gmail.messages.send({
to: contact_email,
subject: 'Invoice [invoice_id] - Payment reminder',
body: rendered_template,
attachment: invoice_pdf_url
})
ACTION 4: FullSpec.log({
invoice_id, sent_at, recipient, reminder_tier,
pay_link, send_status, retry_count
})
ON FAILURE: retry x2, then -> human review queue
// ─── DECISION: Client reply detected? ───────────────────────────────────────
IF Gmail inbound reply detected on watched thread:
-> Route thread to bookkeeper inbox label 'Chase - Reply'
-> PAUSE automation for this invoice_id pending human action
-> [HUMAN HANDOFF: Bookkeeper handles reply, promise to pay, or dispute]
// ─── STAGE 3: Payment Reconciliation Agent ───────────────────────────────────
TRIGGER A: Stripe webhook payment.succeeded { payment_intent_id, amount, metadata.invoice_id }
TRIGGER B: Xero bank feed payment detected against open invoice
MATCH LOGIC:
amount_paid >= amount_due:
-> Xero.Payments.create({ InvoiceID, Amount, Date, Account })
-> invoice.status = 'PAID'
-> Remove invoice_id from chase queue
-> FullSpec.notify(team, 'Invoice [invoice_id] paid in full')
0 < amount_paid < amount_due:
-> Record partial in Xero
-> invoice.status = 'PARTIAL'
-> Recalculate remaining_balance
-> Re-queue chase reminder for remaining_balance at current tier
-> FullSpec.notify(team, 'Partial payment received for [invoice_id]')
No match found:
-> Log unmatched payment -> human review queue
-> [HUMAN HANDOFF: Bookkeeper investigates]
// ─── OUTPUT ─────────────────────────────────────────────────────────────────
RESULT: Invoice marked PAID in Xero
Chase queue entry removed
Reconciliation record written to FullSpec activity log
Team notification dispatched
[HUMAN HANDOFF for disputes and escalations only]04Security and compliance requirements
All items below must be reviewed and confirmed before go-live. Items marked amber require explicit client confirmation. Items marked green are implementation standards the developer applies by default.
Requirement
Detail
Standard
Status
Xero OAuth 2.0 scope
Request minimum scopes: accounting.transactions, accounting.contacts.read, files.read. Do not request payroll or settings scopes.
Principle of least privilege
To confirm with client
Gmail OAuth 2.0 scope
Request gmail.send and gmail.readonly (for reply detection) only. Do not store email content beyond the activity log summary.
Minimum OAuth scope
To confirm with client
Stripe API key type
Use a Restricted Key scoped to checkout.sessions:write and payment_intents:read. Never use the Secret Key in the automation layer.
Stripe restricted keys
Developer to implement
Credential storage
All API keys, OAuth tokens, and webhook secrets stored in the FullSpec Automation secrets vault. Never in environment variables in plain text or in source code.
Encrypted secrets store
Developer to implement
Token refresh handling
Xero access tokens expire after 30 minutes. The orchestration layer must implement automatic token refresh using the stored refresh token. Alert on refresh failure.
Automated refresh with alert
Developer to implement
Sensitive account exclusion
Invoices tagged with a dispute flag or a client-defined sensitive label in Xero must be excluded from all automated actions. The exclusion list must be configurable by the client without a code deploy.
Config-driven exclusion list
To confirm flag convention with client
Data residency
Confirm whether the client requires data to remain in a specific region. FullSpec Automation default region is US-East. Xero data residency follows the client's Xero tenant region.
Region match required
To confirm with client
PII handling
Contact email addresses and invoice amounts are the only PII fields in transit. They must not be written to logs beyond the minimum activity record. Log retention is 90 days unless the client requires longer.
Minimal PII logging, 90-day retention
To confirm retention policy
Stripe webhook signature validation
All inbound Stripe webhook events must be validated using the Stripe-Signature header and the webhook signing secret before processing. Reject unsigned events with HTTP 400.
HMAC signature validation
Developer to implement
Xero webhook validation
Xero delivers webhooks with an HMAC-SHA256 signature header. Validate every payload before acting. Return HTTP 200 for valid events only; return HTTP 401 for invalid signatures.
HMAC-SHA256 validation
Developer to implement
Email template approval
All reminder email templates (LOW, MEDIUM, HIGH, ESCALATE) must be reviewed and signed off by the client and a partner before the Reminder Sender Agent is activated.
Written sign-off required
To confirm with client
Audit log integrity
The FullSpec activity log for every send and reconciliation event must be immutable post-write. No delete or overwrite operations permitted on log records. Access restricted to admin role only.
Immutable append-only log
Developer to implement
Developer Handover PackPage 3 of 4
FS-DOC-04Technical
05Pre-build checklist
The checklist is split into two tracks. The client must complete their items before the developer can begin integration work. The developer track runs in parallel where possible but depends on client credentials being available by the end of Week 1.
Client items should be completed before the Week 1 integration window. Any delay to Xero API access or Stripe account provisioning will push the Chase Scheduler Agent build into Week 2.
Client to provide:
Xero API access confirmed : Client must have an active Xero subscription with API access enabled. A Xero OAuth 2.0 app must be created in the Xero Developer Portal and the client ID and secret shared with the developer via the secrets vault, not email.
Stripe account active and live keys accessible : Confirm the Stripe account is in live mode. The developer will generate a Restricted Key; the client must have admin access to do so. Confirm the default currency and any tax handling requirements.
Gmail account for sending reminders : Identify the Gmail address that reminders will be sent from. The account owner must be available to complete the OAuth consent screen during the integration window. Confirm whether replies should route to the same inbox or a separate monitored address.
Reminder cadence and timing agreed : Confirm the overdue thresholds for each reminder tier (Day 1, Day 7, Day 14, Day 30 or equivalent). Confirm preferred send time of day and time zone. This drives the Chase Scheduler Agent staging rules and must be signed off before build begins.
Email templates reviewed : Draft reminder email content for LOW, MEDIUM, HIGH, and ESCALATE tiers. A partner must sign off on tone and wording before the Reminder Sender Agent is activated. Templates should be provided as plain-text documents with merge field placeholders marked.
Sensitive or disputed account list : Provide a list of contact IDs or naming conventions used in Xero to flag accounts that must never receive automated reminders. This list will be loaded into the exclusion config on day one of the build.
FullSpec Automation account provisioned : Confirm the FullSpec Automation workspace is active and the developer has been granted admin access. The client should confirm their subscription tier covers the expected automation run volume (~318 runs/month).
Data residency preference confirmed : Confirm whether a specific cloud region is required for data processing. If no preference, US-East default applies.
Developer to set up:
FullSpec Automation workspace configured : Create dedicated workflows for each agent. Set up the secrets vault entries for Xero client ID, client secret, refresh token, Stripe restricted key, Gmail OAuth tokens, and Xero webhook signing secret.
Xero OAuth 2.0 app integration built and token refresh implemented : Complete the OAuth 2.0 authorisation code flow. Store access and refresh tokens in the vault. Implement the automatic refresh cycle with failure alerting. Validate that minimum scopes (accounting.transactions, accounting.contacts.read, files.read) are working correctly.
Xero webhook endpoint provisioned and HMAC validation implemented : Register the FullSpec webhook endpoint in the Xero Developer Portal. Implement HMAC-SHA256 signature validation on every inbound payload before any data processing occurs.
Stripe restricted key created and webhook endpoint registered : Create a restricted API key in the Stripe dashboard with checkout.sessions:write and payment_intents:read scopes only. Register the payment.succeeded webhook and implement Stripe-Signature HMAC validation.
Gmail OAuth integration and reply-detection watch configured : Complete Gmail OAuth consent for the sending account. Configure Gmail API push notifications or polling to detect inbound replies on tracked threads. Implement the routing logic to label reply threads for the bookkeeper.
Chase queue data store initialised : Set up the FullSpec queue store that holds staged reminder entries. Confirm schema matches the IO spec in Section 02. Implement deduplication logic to prevent double-sends for the same invoice tier.
Exclusion list config loaded : Load the client-provided sensitive account list into the parameterised exclusion config. Confirm the Chase Scheduler Agent skips flagged contact IDs correctly before activating on live data.
Activity log schema created and write access confirmed : Initialise the immutable activity log in FullSpec. Confirm append-only permissions are set and no delete operations are available to standard users. Set retention policy to 90 days (or client-specified period).
Local test environment with Xero sandbox and Stripe test mode : Use Xero's demo company and Stripe test mode for all development and QA work. No live invoice data should be touched until end-to-end QA sign-off in Week 4.
06Recommended build stack
Tool
Role
Auth method
Monthly cost
Notes
FullSpec Automation
Orchestration, queue management, activity logging, alerting
API key (internal)
$145/month
Primary automation platform; all agent workflows built here
Xero
Invoice data source, payment recording, reconciliation
OAuth 2.0 (PKCE, 30-min token, auto-refresh)
$0 (client's existing subscription)
Minimum scopes: accounting.transactions, accounting.contacts.read, files.read
Stripe
Pay link generation, payment event source via webhook
Restricted API key + webhook signing secret
$0 (transaction fees apply separately)
Use Checkout Sessions API; test mode for QA, live mode post sign-off
Gmail
Outbound reminder delivery, inbound reply detection
OAuth 2.0 (gmail.send, gmail.readonly)
$0 (client's existing Google Workspace)
One sending account; reply-watch via push notification or polling
Total build effort
56 hours
Week 1
Foundation and integrations: provision environment, connect Xero, Stripe, Gmail with secure auth
Week 1 to 2
Chase Scheduler Agent: overdue detection, staging rules, queue writes
Week 2 to 3
Reminder Sender Agent: template rendering, Stripe pay link generation, Gmail send, activity logging
Week 3 to 4
Payment Reconciliation Agent: payment matching, partial handling, Xero status update, team notification
Week 4
End-to-end QA and launch: regression against historical invoices, partner sign-off, go-live with monitoring
All development and QA work must use Xero demo company data and Stripe test mode. Switching to live credentials requires written partner sign-off and completion of all items in Section 05. The target auto-match rate for payment reconciliation is 96%; a tuning period of 1 to 2 weeks against real payment data is expected after go-live before this rate stabilises.
Developer Handover PackPage 4 of 4