What this audit checks
Authentication & access
- OAuth2 token refresh against /auth/oauth/token succeeds (grant_type=refresh_token, client_id + client_secret + refresh_token)
- Identity probe GET /auth/api/v1/users/me returns the token owner with at least one business_membership carrying account_id (and business_id if Projects is used)
- Granted scopes cover the resources the cards read (user:invoices:read, user:payments:read, user:clients:read, user:expenses:read)
- Sustained 429 / rate-limit responses indicate the OAuth app quota is saturated by other integrations
Cash-flow & AR health
- Sent invoices overdue >30d with outstanding balance and no payment recorded (recoverable cash sitting idle)
- AR aged 60+ days above 15% of total outstanding balance
- Days Sales Outstanding (DSO) above 60 days over trailing 30d
- Total outstanding AR rising >20% vs trailing 30d without a matching rise in invoice volume (collections drag)
Invoicing hygiene
- Invoices stuck in draft >7d (revenue not yet billed to the client)
- Sent invoices with no view event after 14d (delivery / email problem)
- Invoices missing a due_date (no aging signal - falls out of collections rhythm)
- Partial payments left open >30d without a follow-up reminder
Expense & tax readiness
- Expenses with no category assigned in the last 90d (quarterly tax estimate hard to compute)
- Expense total spiking >25% vs prior 90d period without a matching revenue change
- Duplicate expenses (same amount + vendor + date) suggesting a double-import
Cross-channel: FreshBooks vs ecommerce & payments reconciliation
- Storefront order has no matching FreshBooks invoice after the sync window (sibling = bigcommerce.order / shopify.order / adobe_commerce.order, by po_number/order_reference or client email)
- Stripe/PayPal payout has no matching FreshBooks payment within the reconciliation window (sibling = stripe.charge / paypal.transaction, by amount+date - AR overstated / double-count risk)
- Ecom customer with completed orders absent from FreshBooks client master after 7d (sibling = bigcommerce.customer / shopify.customer, by email)
- Customer with AR aged 60+ days still placing new ecom orders (credit risk compounding, sibling = ecommerce customer by email)
Data sources
POST /auth/oauth/token- OAuth2 token refreshGET /auth/api/v1/users/me- Identity / account_id + business_id resolution probeGET /accounting/account/{account_id}/invoices/invoices- Invoices - AR, aging, DSO, overdue, status, outstandingGET /accounting/account/{account_id}/payments/payments- Payments - recorded payments for PSP reconciliationGET /accounting/account/{account_id}/users/clients- Clients - customer master parity by emailGET /accounting/account/{account_id}/expenses/expenses- Expenses - categorisation + tax-readiness checks