Pass-through architecture
Your transaction data never sits on our servers. Here’s the complete data flow:
- Your bank → PlaidBank authentication handled exclusively by Plaid. SheetLink never sees your credentials
- Plaid → SheetLink APIToken exchange only, no transaction data stored at this step
- SheetLink API fetches transactionsData exists in memory for less than 1 second during sync, then deleted
- SheetLink → Your destinationWritten directly to Google Sheets, Excel, Postgres, SQLite, JSON, or CSV: your data, your storage
Guarantee: Transaction data exists on SheetLink servers for less than a second during sync, just long enough to fetch from Plaid and return to your client. Nothing is cached or logged.
What we store
We do store
- Plaid access tokens. Fernet-encrypted (AES-128-CBC + HMAC). Decrypted only during sync.
- Google user ID + email. Used to restore your connections across devices.
- Sheet metadata. Sheet ID and title, to write transactions to the right destination.
- Plaid metadata. Item IDs, institution IDs, sync cursors. No transaction content.
- Subscription tier. Free, Pro or Max, to enforce feature limits server-side.
We never store
- Transaction amounts, merchants, categories, or dates
- Account balances or transaction history
- Bank usernames or passwords (Plaid handles these)
- Google OAuth tokens (stay in your browser)
- Your spreadsheet or database contents
JWT authentication
Authentication flow
- User signs in with Google OAuth
- Backend verifies Google ID token with Google’s API
- Backend generates a signed JWT (4-hour expiry)
- Extension stores JWT in Chrome’s encrypted storage
- All API requests send JWT in Authorization header
- Backend verifies signature and enforces tier limits on every request
Token security
- Cryptographic signatures: tokens can’t be tampered with
- 4-hour expiry: limited validity window
- HTTPS only: encrypted in transit
- Stateless: no server-side session tracking
Protected endpoints
/tier/status/plaid/sync/plaid/backfill
Plan limits are enforced on the server: a Free account can’t use Pro or Max features, even with modified client code.
Minimal extension permissions
The Chrome extension requests only what’s needed to function:
storage: Store encrypted tokens and user preferences locallyidentity: Google OAuth authenticationalarms: Schedule JWT token refresh before expiryhost permissions: googleapis.com (Sheets/Drive APIs), script.googleapis.com and raw.githubusercontent.com (installing recipes into your sheet), cdn.plaid.com (Plaid SDK), api.sheetlink.app (SheetLink backend)
Not requested: Browsing history, access to other websites, clipboard, camera, or microphone.
API security
- CORS restrictions: Only SheetLink domains and extension IDs allowed
- Input validation: All user input sanitized and validated
- Privacy middleware: Sensitive data automatically suppressed from logs on Plaid endpoints
- Sheet permission check: Write access verified before connecting a sheet
- HTTPS / TLS 1.2+: All communication encrypted in transit
Third-party security
Microsoft
- Office.js API for workbook writes
- Managed dialog for OAuth and Plaid
- SheetLink does not send workbook data to Microsoft
Anthropic Max
- Claude AI for conversational transaction queries
- Data sent to Anthropic API on your behalf only
- SheetLink does not retain data submitted to Claude
Audit the code yourself
The Chrome extension, the CLI and the MCP server are open source on GitHub. Review every line before installing.
View on GitHub ›Privacy policy ›
Report a vulnerability
If you discover a security issue, please report it responsibly. Do not publicly disclose before we’ve patched it.
- Email: security@sheetlink.app
- Response time: Within 48 hours
- Disclosure: Coordinated with you. We’ll credit researchers in release notes (with permission)