Skip to content

Security & trust

You’re connecting your financial data. Here’s exactly how it’s handled.

This page describes what JobProfitAI actually does, not a list of badges. It also says plainly what we have not done, because a security page that only lists good news isn’t useful to anyone making a real decision.

What we don’t claim

JobProfitAI does not hold SOC 2, SOC 2 Type II, ISO 27001, HIPAA or PCI certification, and has not completed a third-party penetration test or security audit. We’re a young product and we’re not going to put badges on this page that we haven’t earned. What follows is a factual description of the controls that are actually in place today.

QuickBooks connection

How the QuickBooks authorization works

You authorize through Intuit, not through us

Connecting uses Intuit’s standard OAuth 2.0 flow. You’re redirected to Intuit’s own website to sign in and approve access. Your QuickBooks username and password are never entered into JobProfitAI, never transmitted to our servers, and never stored by us in any form.

The authorization endpoints we use are read from Intuit’s live OAuth discovery document rather than hardcoded, so we follow Intuit’s current configuration.

The connection request is protected against forgery

Each connection attempt carries a short-lived, cryptographically signed state token tied to your logged-in session and valid for ten minutes. When Intuit redirects back, that signature is verified, and the callback is only accepted in the same signed-in browser that started it, before anything is stored. A callback with a missing, expired or altered state token, or one arriving in someone else’s browser, is rejected rather than trusted. A QuickBooks company that is already connected to another JobProfitAI account is never moved: the attempt is refused and that account’s owner is told.

What JobProfitAI does with the access it's given

JobProfitAI only reads from QuickBooks. It does not create, modify or delete invoices, bills, customers, projects or any other record in your books. Every call the application makes to QuickBooks is a read.

To be precise rather than reassuring: the connection uses Intuit’s standard accounting scope, which is the scope Intuit provides for accounting data access. We describe our behaviour as read-only because that is what the software does, not because Intuit issues a separate read-only credential.

Tokens and your company ID are encrypted before storage

The OAuth access token, the refresh token, and your QuickBooks company (realm) ID are each encrypted with AES-256-GCM at the application layer before they are written to the database. The encryption key lives in the server environment, never in the database and never in source control, so a database dump or backup on its own does not yield usable credentials.

Because encrypted values can’t be searched, we also store a one-way keyed hash (HMAC-SHA-256, with a key held only in the server environment) of the company ID purely as a lookup key. The plain company ID is never stored.

You can disconnect at any time

Disconnecting from Settings calls Intuit’s token revocation endpoint to invalidate the connection on Intuit’s side, then marks the connection inactive here. You can also disconnect from within QuickBooks itself at any time. Intuit then sends you to a page here that checks with Intuit and marks the company disconnected straight away; if you don’t land there, the next nightly sync notices and shows a Reconnect button rather than silently retrying.

Once a company is disconnected, nothing is synced or calculated for it any more. If QuickBooks stops letting us in and the company isn’t reconnected within a week, it’s treated as disconnected too. Its data is kept for 30 days in case you reconnect, and then deleted. You can delete it sooner from Settings.

Your data

What we store, and what we don't

What is stored

To produce profitability analysis, JobProfitAI stores a copy of the job-related data it reads from QuickBooks: jobs (QuickBooks Projects or sub-customers, customers if you make one customer per job, or Classes if each job is a class, with their names) and the customer each belongs to; cost line items from bills, checks, expenses, vendor credits and journal entries tagged to a job, with the account or product name; job cost lines from the last 12 months that aren’t on any job, with the vendor or payee and memo, so Data Health can list them; time entries as hours and a labor cost; invoice, sales receipt, credit memo and refund totals, status and what’s still owed on open invoices; income from deposits and journal entries recorded against a job; estimates, with each line’s product or service, amount, quantity and the purchase cost set on it in QuickBooks; and the profitability figures calculated from them. It also stores each Weekly Profit Brief, the profit alerts sent, the profit insights generated for you, and your own settings such as target margin and email recipients.

About labor: a time entry’s labor cost is its hours times the cost rate on the entry, which comes from the employee’s cost rate in QuickBooks. The cost rate itself isn’t stored, but it can be worked out from a single entry, so anyone you give a login to can see what an hour of each person’s time costs. If that matters to you, turn off labor from timesheets in Settings.

What is not stored

We do not store your QuickBooks password, your bank account details, your customers’ payment information, payroll records (paychecks, tax details), or document attachments from your QuickBooks file. We do not store credit card numbers. See the billing section below.

Every account's data is isolated from every other account

Each QuickBooks connection belongs to exactly one JobProfitAI account. Every request that touches financial data verifies, on the server, that the signed-in account owns the connection or job being requested, a request for a record belonging to another account returns not-found, regardless of what the browser asks for.

If you invite team members, each has their own login and sees your account’s companies and reports under your plan. Only you can manage billing, invite or remove people, disconnect a company or delete the account. Removing someone signs them out everywhere at once.

On the Firm plan, a bookkeeper connects each client’s QuickBooks company to the firm’s own account and can give a client a view-only login. A client login sees one company, including its dashboard, Data Health and WIP report, and can’t change anything. It never sees the firm’s other clients, its settings or its billing, and every request it makes is checked on the server against that one company.

Being a referral partner or a referrer confers no access to any other business’s financial data whatsoever. Partner dashboards show counts and commission amounts only, never a client’s numbers. A firm sees a client’s numbers only by connecting that client’s QuickBooks company through Intuit, which takes a QuickBooks login with access to it.

Contractors who help us with outreach and sales are not given access to the app, its admin tools, customer accounts or QuickBooks data.

Logging is deliberately restricted

Application error logs record status codes and Intuit’s request-tracing ID only. Raw API responses, request bodies and error objects from QuickBooks are never logged, because those can echo back credentials or customer financial data.

When something goes wrong, an error report goes to Sentry, our error monitoring service: the kind of error, its message with email addresses, tokens, quoted text and amounts taken out, where in our code it happened, and the page or scheduled job it happened on. It is set up to leave out your QuickBooks figures, job and customer names, what was sent to the page, cookies and tokens. Sentry also tells us when a scheduled job, such as the nightly sync, doesn’t run on time.

Advertising and analytics tags stay out of the app

Our public website uses Google Analytics, which also measures our Google Ads, as our Privacy Policy describes. Its tags load only on public pages and the signup page, never in the signed-in app, so they can’t see your QuickBooks figures, jobs or customers. If you move from a public page into the app, the page reloads without them. They don’t load at all if your browser sends Global Privacy Control or you turn them off on our Your Privacy Choices page.

Deleting your account deletes your data

You can delete one company’s data from Settings without deleting your account, for example when a bookkeeping firm stops working with a client. That removes the company’s jobs, costs, invoices, estimates, briefs, alerts, insights, WIP copies and settings, and its client logins lose access.

You can permanently delete your account from Settings. Doing so revokes any live QuickBooks connection with Intuit, cancels any active subscription, and deletes your account together with your QuickBooks connections and tokens, jobs, cost data, invoices, estimates, weekly briefs, alerts, insights and settings. Any team members and client logins lose access at the same moment. Deletion is irreversible and requires re-entering your password.

A few records outlive a deleted account, none of them holding your QuickBooks data. If a partner referred you, the commission records for payments you made are kept so the partner can be paid correctly: they hold amounts, dates and internal and Stripe reference numbers, not your name or email. A record that a referral link led to an account is kept with your account removed from it. For each QuickBooks company that started a free trial or had its data deleted, a keyed hash of its ID, with the date and an internal account number, is kept so the same company can’t start a second free trial. Stripe keeps its own record of your payments, as a payment processor must, and we keep anything the law requires us to. Our Privacy Policy has the full list.

Application & infrastructure

Authentication, transport and hosting

Authentication

Passwords are hashed with bcrypt (work factor 12) and never stored in a recoverable form. Sessions use a signed token in an HTTP-only cookie, which browser JavaScript cannot read, marked Secure in production and scoped with SameSite protection against cross-site request forgery.

Repeated wrong passwords lock sign-in for that address for 15 minutes (the records behind this hold keyed hashes of the address and network address, never the address itself, and are deleted after a day). “Sign out of all devices” in Settings ends every session at once, and so does resetting your password.

If you use Sign in with Intuit, your account is matched on Intuit’s permanent account ID, never on the email address. Intuit must have verified your email, and an Intuit sign-in is only linked to an existing JobProfitAI login after that login’s password has been entered.

Transport

The application is served exclusively over HTTPS. All communication with Intuit, Stripe, our email provider and our error monitoring service is over TLS.

Hosting and database

JobProfitAI runs on Vercel, with a managed PostgreSQL database hosted by Neon. Database access is restricted to the application via a credential held in the server environment. Secrets, meaning database credentials, the token encryption key and API keys, are stored as environment variables in the hosting platform, never committed to source control, and never exposed to the browser.

Payments

Billing is handled by Stripe. Card details are entered on Stripe-hosted pages and are never transmitted to or stored on JobProfitAI systems. We hold only Stripe’s identifiers for your customer and subscription. Stripe is a PCI Service Provider Level 1; that is Stripe’s certification, not ours, and it applies to their handling of card data.

Incoming billing events from Stripe are cryptographically signature-verified before being processed, so a forged request cannot alter your subscription state.

Email

Transactional email, meaning your Weekly Profit Brief and trial and billing notices, is sent through Resend from a verified JobProfitAI sending domain. Emails go only to the address on your account and the recipients you configure (up to 10), and the Weekly Profit Brief and profit alerts aren’t sent until you’ve confirmed your own address. Every recipient can unsubscribe with one click.

Artificial intelligence

Advisor notes on your profit opportunities, the written summary in the Weekly Profit Brief, and job type suggestions you ask for are produced by Anthropic’s Claude API, with each request set to run only on Anthropic’s US infrastructure. What is sent is the calculated profitability data for your jobs: job names, the customer names attached to them, job types and computed figures (for job type suggestions, just job and customer names and your job type names). The model writes explanatory prose only; the “What changed” section of the brief is calculated, not written by it. Every dollar amount, percentage and confidence level in a finding is calculated by the application and stored separately from the text, and each finding names the jobs it came from, so you can check any figure against the job pages. Your QuickBooks credentials are never sent to any AI service.

Security questions, or something to report?

We’d rather hear from you than not. If you have a question about how your data is handled, or believe you’ve found a vulnerability, email us directly and we’ll respond.

support@jobprofitai.com

See also our Privacy Policy and Terms of Service.