WWebBuddyMarketplace
Integrations and billing

Integrations

Each bank, email, sign-in, Slack, accounting and utility integration, what it really does in version 0.1.0, how to set it up, and its redirect URIs.

6 min readUpdated Oct 17, 2026Applies to Subsweep 0.1.0

On this page

Every integration is optional and switches on when its environment variables are set (Configuration). In production, a missing key means that feature says it is not available; the sample data used in development is never shown.

Status at a glance

Integration Status in 0.1.0 Needs
Plaid (US, Canada) Works: 12-month import, then an hourly sync PLAID_CLIENT_ID, PLAID_SECRET, PLAID_ENV
TrueLayer (UK) Imports 12 months once; later syncs bring in nothing once the access token expires TRUELAYER_CLIENT_ID, TRUELAYER_CLIENT_SECRET
Salt Edge (EU) Return flow fixed, but not tested against a live Salt Edge account SALTEDGE_APP_ID, SALTEDGE_SECRET; test before offering it
Setu Account Aggregator (India) Not reachable from the interface Leave unset
Gmail receipts Works for a scan at connect time Google OAuth client
Outlook receipts Works for a scan at connect time Microsoft app registration
Google sign-in Works GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
SMTP or Resend email Works See Outbound email
Stripe Billing Works, with caveats See Plans, billing and selling it as SaaS
Slack Connects; alerts need a manual switch SLACK_CLIENT_ID, SLACK_CLIENT_SECRET
QuickBooks Online, Xero Connect works; Export now does not reach live data Leave unset for now
Google Workspace, Notion, Zoom usage No screen, no data fetched Leave unset
Open Exchange Rates Works OPEN_EXCHANGE_RATES_APP_ID
Cloudflare R2 Upload request is not signed correctly Leave unset
Sentry (browser) Works NEXT_PUBLIC_SENTRY_DSN
PostHog Does not initialise Leave unset
Inngest Sends one event per hourly run INNGEST_EVENT_KEY

Bank feeds

The bank provider is chosen from the workspace's country:

Country Provider
United States, Canada Plaid
United Kingdom TrueLayer
EU member states Salt Edge
India and anywhere else None: statements, email and manual add instead

Onboarding and Settings offer five countries: the United States, Canada, the United Kingdom, Germany (for the EU) and India. Bank connections are a Pro feature.

Plaid

  1. Create an app in the Plaid Dashboard with the Transactions product, and copy the client ID and secret for the environment you are using.
  2. Set PLAID_CLIENT_ID, PLAID_SECRET and PLAID_ENV (sandbox, development or production). Production use needs Plaid's approval.
  3. Connect bank opens Plaid Link in the browser. On success, Subsweep imports up to 12 months, and the hourly job then pulls the last 48 hours on every run.

Good to know: Plaid amounts are imported as positive values whether money went out or came in; the detection engine filters out most non-software rows. PLAID_REDIRECT_URI is passed to Plaid Link, but there is no page that resumes Link after an OAuth bank's redirect, so banks that require that flow may not complete.

TrueLayer

Set TRUELAYER_CLIENT_ID, TRUELAYER_CLIENT_SECRET and, for live banks, TRUELAYER_ENV=production. Add <BETTER_AUTH_URL>/api/oauth/truelayer/callback as a redirect URI in the TrueLayer console.

The connection imports 12 months of transactions. TrueLayer access tokens are short-lived and Subsweep does not refresh them yet. Once the token expires, the hourly sync quietly brings in nothing while the source still looks connected. Treat it as a one-off import per connection for now: disconnect and reconnect to import newer transactions.

Salt Edge and Setu

Both return pages check who comes back. When a connection is started, Subsweep stores a single-use state for that workspace, valid for 20 minutes. The return page attaches the bank only if that state is found and the person returning is signed in as an Owner or Editor of its workspace; otherwise they land on Sources with an error.

  • Salt Edge: the connect session asks Salt Edge to return the connection ID. The return page checks with Salt Edge that the connection belongs to the customer created for this workspace, then stores the connection ID, which is what transaction fetches use.
  • Setu Account Aggregator: India workspaces have no bank provider, so nothing in the interface starts a Setu consent, even with SETU_AA_ENABLED=true. Leave it unset. Its return page uses the consent ID stored with the state, and refuses a different ID or success=false.

Warning

The Salt Edge flow has not been tested against a live Salt Edge account or sandbox. Connect a test bank with your own Salt Edge credentials, and check that transactions arrive, before you offer it to customers.

Email receipts

Both connections are read-only and a Pro feature. They scan when the mailbox is connected (and when someone presses scan again); the hourly job does not re-scan. See Email receipts for what is read.

Gmail

  1. In Google Cloud Console, enable the Gmail API and configure the OAuth consent screen with the https://www.googleapis.com/auth/gmail.readonly scope.
  2. Create an OAuth client of type Web application with the redirect URI <BETTER_AUTH_URL>/api/oauth/gmail/callback.
  3. Set GMAIL_CLIENT_ID and GMAIL_CLIENT_SECRET. If you leave them empty, the Google sign-in client is used, so that client then needs the Gmail redirect URI and scope as well.

gmail.readonly is a restricted scope: until Google has verified your app, connecting is limited (test users, or a capped number of people who see an unverified-app warning). See restricted scope verification.

Outlook

  1. Register an app in Microsoft Entra with the delegated permissions Mail.Read and offline_access.
  2. Add the web redirect URI <BETTER_AUTH_URL>/api/oauth/outlook/callback and create a client secret.
  3. Set MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET and, for a single-tenant app, MICROSOFT_TENANT.

Note

Not in this version yet: token refresh for either mailbox. A scan more than about an hour after connecting quietly finds nothing new, because the stored access token has expired. Reconnect the mailbox from Settings → Integrations to scan again.

Google sign-in

Create a Google OAuth client (Web application) with the redirect URI <BETTER_AUTH_URL>/api/auth/callback/google, then set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET. "Continue with Google" appears on the sign-in and sign-up pages once both are set. Sign-in only needs basic profile scopes, so it does not need the restricted-scope review that Gmail scanning does.

Slack

  1. Create a Slack app at api.slack.com/apps with the bot scopes chat:write, channels:read and incoming-webhook.
  2. Add the redirect URL <BETTER_AUTH_URL>/api/oauth/slack/callback.
  3. Set SLACK_CLIENT_ID and SLACK_CLIENT_SECRET.

Connect from Settings → Integrations and pick a channel during Slack's install screen. Alerts are only posted once the per-alert Slack switch is on, and that switch is not in the interface yet: see Slack for the workaround.

QuickBooks Online and Xero

Settings → Integrations can connect either one over OAuth (redirect URIs <BETTER_AUTH_URL>/api/oauth/quickbooks/callback and <BETTER_AUTH_URL>/api/oauth/xero/callback), and the QuickBooks card has an Export now button that sends active subscriptions as bills.

Warning

Not ready for live use in 0.1.0. The QuickBooks export always calls Intuit's sandbox API with a placeholder company instead of the connected company's ID; the Xero export does not send the tenant header Xero requires; neither refreshes expired tokens; and responses are not checked, so the app reports success even when nothing was created. There is no category-to-account mapping and no scheduled export.

Usage insights

Routes exist to start OAuth with Google Workspace, Notion and Zoom (/api/oauth/usage/<provider>/start), but no screen links to them, and the callback only stores the authorisation code: no seat or activity data is fetched. Seat savings come from Offboarding instead.

Exchange rates

With OPEN_EXCHANGE_RATES_APP_ID set, every hourly run fetches the latest USD rates from Open Exchange Rates for USD, CAD, GBP, EUR and INR, roughly 720 requests a month. Check that your Open Exchange Rates plan allows that. Without a key, fixed fallback rates are used.

Utilities

Service Behaviour in 0.1.0
Cloudflare R2 Attachments are sent with the access key ID as a bearer token instead of a signed S3 request, so uploads fail silently. Leave it unset and attachments go to local disk.
Sentry Browser errors are reported when NEXT_PUBLIC_SENTRY_DSN is set at build time.
PostHog The loader calls PostHog before its script has loaded, so it never starts.
Inngest Each hourly run sends a subsweep/jobs.tick event. No jobs run in Inngest.

Redirect URIs and webhooks

Replace https://subs.example.com with your BETTER_AUTH_URL.

Provider URL
Google sign-in https://subs.example.com/api/auth/callback/google
Gmail https://subs.example.com/api/oauth/gmail/callback
Outlook https://subs.example.com/api/oauth/outlook/callback
TrueLayer https://subs.example.com/api/oauth/truelayer/callback
Slack https://subs.example.com/api/oauth/slack/callback
QuickBooks https://subs.example.com/api/oauth/quickbooks/callback
Xero https://subs.example.com/api/oauth/xero/callback
Stripe webhook https://subs.example.com/api/webhooks/stripe
Hourly job https://subs.example.com/api/cron/tick