> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ai2fin.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Enabling Google Sheets in a desktop build (operator setup)

> How to register a Google OAuth client so the AI2Fin desktop app can offer live Google Sheet sync. A one-time setup for whoever packages the build.

<Info>
  This page is for whoever **packages the desktop build**, not for end users. If
  you are using the app and see "Live Google Sheet sync isn't switched on for
  this deployment yet", that means this setup has not been done for your build —
  CSV import works regardless, and a synced sheet can be imported as a file.
</Info>

## Why a setup step exists

The desktop app connects a Google Sheet through Google's own OAuth, using the
**installed-app pattern**: the user approves in their real browser, and Fin gets
read access to exactly the one sheet they pick (`drive.file` scope) — never
their whole Drive, never their Google password.

That flow needs a **Google OAuth client of type "Desktop app"**, registered
once. The client id ships in the binary (which is sanctioned for installed
apps — PKCE is what protects the exchange, not a secret). Until a build carries
one, the app honestly says the feature is not switched on rather than offering a
button that fails.

## One-time registration

<Steps>
  <Step title="Create a Desktop app OAuth client">
    In the Google Cloud Console → **APIs & Services → Credentials → Create
    credentials → OAuth client ID**, choose application type **Desktop app**.
    Desktop clients permit loopback redirects on any port, which is what makes
    the OS-assigned local port work.
  </Step>

  <Step title="Enable the APIs">
    Enable the **Google Sheets API** and the **Google Drive API** for the
    project. The Drive API backs the `drive.file` scope; Sheets reads the rows.
  </Step>

  <Step title="Configure the consent screen for drive.file">
    `drive.file` is a **non-sensitive** scope (per-file access the user grants
    explicitly), so it does not require Google's restricted-scope security
    assessment. Fill in the consent screen and publish it. Add test users while
    it is in testing.
  </Step>

  <Step title="Set the build's environment">
    The packaged desktop build reads these:

    | Variable                | Purpose                                                                            |
    | ----------------------- | ---------------------------------------------------------------------------------- |
    | `GOOGLE_CLIENT_ID`      | The Desktop-app client id. Required — its absence is what shows "not switched on". |
    | `GOOGLE_CLIENT_SECRET`  | Optional for a desktop client; PKCE is the real protection.                        |
    | `GOOGLE_PICKER_API_KEY` | Only the cloud/web Picker uses this. The desktop paste-link flow does not need it. |

    No redirect URI needs pre-registering: desktop clients allow loopback, and
    the app computes `http://127.0.0.1:<port>/api/feeds/google/desktop/callback`
    from the running server.
  </Step>
</Steps>

## What the user then sees

With the client id present, the connector card offers **Connect a Google
Sheet**: the user pastes their sheet's link, a browser tab opens for approval,
and the app completes the connection and proposes a column mapping — the same
"check the columns" step the web app uses.

<Card title="How sync behaves once connected" icon="rotate" href="/data-sources/connections">
  Fin reads the sheet on a schedule; rows are fingerprinted so re-reading the same
  sheet changes nothing, and a row that disappears is flagged rather than deleted.
</Card>

## If approval fails to renew

Google issues a **renewable** authorisation only the **first** time a user
approves an app. If a user connected before, revoked, and reconnects, they may
get a one-hour token with nothing to renew. The app detects this and tells them
to remove Fin from their Google account permissions and connect again — which
makes Google issue a fresh renewable token.
