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

# Gmail Sync

> Connect Gmail with read-only access, search for dispensary receipts, review candidate emails, and import selected orders.

## What Gmail Sync does

Gmail Sync searches a connected Gmail account for likely dispensary receipts,
lets you choose candidate emails, and turns each confirmed receipt into its own
order. Historical Import also requests one notebook for every confirmed
historical order. Quick Sync follows the normal Gmail access policy; Historical
Import is a separately flagged, one-time archive purchase. Both use Google's
read-only `gmail.readonly` permission.

<Info>
  The complete implemented flow is maintained in
  [Order Activation](/help/user-flows/order-upload). That page is the source of
  truth when this guide and older planning material disagree.
</Info>

## Before you start

For the most accurate search, save the dispensary where you shop and associate
a receipt email domain with it. A shop is **Quick Sync-ready** only when it has
at least one `emailDomains` value.

The Add/Edit Shop form and Gmail's inline shop setup both manage confirmed
receipt domains. Contact email and website can suggest a domain, but Gmail does
not search it until the user confirms it.

## Connect Gmail

<Steps>
  <Step title="Open Add Order">
    Open the order-upload hub and choose Gmail Sync.
  </Step>

  <Step title="Connect or reauthorize Google">
    High IQ opens Google's OAuth flow and requests read-only Gmail access. A
    Google sign-in by itself does not include this permission.
  </Step>

  <Step title="Confirm the connection">
    After Google returns to the app, Clerk refreshes the account scopes and
    Convex verifies the Google connection server-side before enabling scans.
  </Step>
</Steps>

High IQ cannot send, modify, or delete email. OAuth tokens are retrieved
server-to-server and are not exposed to the mobile app.

## Historical import

Historical discovery supports up to 2,000 candidate receipts per import. That
is a configurable global scan cap, not a per-shop or per-query allowance. You
can complete the free discovery and preview before the one-time purchase is
required.

<Steps>
  <Step title="Choose a date range">
    The default is the largest configured archive range, currently **Up to the
    past 10 years**. You can narrow it to 6 months, 12 months, 2 years, 3 years,
    or a custom range. The archive horizon is configurable up to 22 years.
  </Step>

  <Step title="Start the scan">
    Choose one or more Gmail-ready saved shops for a targeted domain scan. A
    broader community and keyword search is available only as an explicit
    secondary option.
  </Step>

  <Step title="Review dispensary groups">
    Turn groups on or off. This controls which candidate emails continue.
    Validated sender domains are attached to the linked shop only after the
    resulting order is reviewed and confirmed.
  </Step>

  <Step title="Review candidate emails">
    Inspect sender, subject, date, snippet, classification confidence, and the
    estimated summary. Candidates are loaded in pages so large archives remain
    responsive. Select only messages you want imported.
  </Step>

  <Step title="Unlock and parse the archive">
    After the free preview, restore an existing entitlement or complete the
    one-time Historical Import purchase. High IQ then fetches and parses the
    selected email bodies in bounded background chunks. Each successful parse
    becomes a staged review, not an order.
  </Step>

  <Step title="Review each parsed receipt">
    Correct the shop, date, total, names, matches, quantities, units, prices,
    selection, and unknown-strain confirmations. Save it or explicitly skip it.
    Duplicates, no-item results, and failures are reported separately.
  </Step>

  <Step title="Confirm safe orders faster">
    Fully resolved, high-confidence receipts can be confirmed in safe bounded
    groups. Anything incomplete, ambiguous, or unmatched stays in the
    individual editable review queue.
  </Step>

  <Step title="Explore the archive">
    Every confirmed receipt becomes an individual order and requests its own
    notebook. Open **Stash → Orders** to search, filter, and inspect the complete
    purchase archive while notebook and strain research work continues.
  </Step>
</Steps>

<Note>
  A Gmail candidate is never an order by itself. `totalImported` increments
  only after the staged receipt has passed Review & Confirm and committed.
</Note>

```mermaid theme={null}
flowchart TD
    A[New user finishes sign-in] --> B[Find Past Orders]
    B --> C{Gmail-ready saved shop?}
    C -->|No| D[Add shop and confirm receipt domain]
    C -->|Yes| E[Choose saved shops]
    D --> E
    E --> F[Free targeted discovery]
    F --> G[Optional explicit broad search]
    F --> H[Paged candidate review]
    G --> H
    H --> I{Archive access?}
    I -->|Production| J[Restore or buy one-time entitlement]
    I -->|Staging or local bypass enabled| K[Exercise full flow without purchase]
    J --> L[Parse selected receipts in bounded chunks]
    K --> L
    L --> M[Durable outcome ledger]
    M --> N{Parsed receipt quality}
    N -->|Fully resolved and high confidence| O[Confirm next safe group]
    N -->|Needs attention| P[Edit one receipt]
    P --> Q{Unknown name is cannabis?}
    Q -->|Yes| R[Queue strain research after order commit]
    Q -->|No| S[Keep line without research]
    O --> T[One committed order per receipt]
    R --> T
    S --> T
    T --> U[Request one notebook per historical order]
    T --> V[Stash → Orders archive]
    L --> W{Interrupted or failed?}
    W -->|Remount| X[Reopen active job and continue durable state]
    W -->|Some messages failed| Y[Retry failed messages only]
    W -->|User cancels| Z[Cancel runs best-effort and discard pending drafts]
```

## Quick Sync

Quick Sync is for returning users. It displays saved shops, preselects the most
recent Quick Sync-ready shop, and searches the selected domains.

<Steps>
  <Step title="Choose shops">
    Select one or more shops with receipt email domains. Shops marked **Needs
    domain** cannot be selected for Quick Sync.
  </Step>

  <Step title="Sync the last seven days">
    High IQ uses Gmail History when a valid cursor exists. If no cursor exists
    or it expired, the backend uses a bounded fallback without silently skipping
    unprocessed history.
  </Step>

  <Step title="Review new candidates">
    Select the candidate emails you want. Found candidates are not counted as
    imported orders.
  </Step>

  <Step title="Import selected orders">
    The same batch parser and idempotent order writer used by historical import
    processes the selected messages.
  </Step>
</Steps>

If no candidates are found, try another saved shop, use **Advanced Options**
for a broader historical scan, or use text input.

## What happens after import

| Result              | Behavior                                                                                           |
| ------------------- | -------------------------------------------------------------------------------------------------- |
| Success             | Creates one confirmed order and preserves every valid parsed line.                                 |
| Duplicate           | Reuses the Gmail message ID check and does not create another order.                               |
| No items            | Keeps the email result in the completion summary; no empty order is created.                       |
| Failed              | Lists the result for a failed-only retry. Successful messages are not replayed.                    |
| Resolved strain     | Links the authoritative strain identity. Gmail history still does not auto-add it to active stash. |
| Unresolved strain   | Saves the line and queues background research under the current order-upload policy.               |
| Historical notebook | Requests one notebook for each committed historical order.                                         |

Gmail imports use `addToStash: false`; importing purchase history never changes
active inventory automatically. Historical Import requests a notebook for every
committed order. From order detail, users can still add eligible resolved items
to Stash or manage notebook state when policy allows it.

## Resume, retry, and cancel

* Leaving the app does not abandon the archive. Reopening Historical Import or
  tapping the active-import banner in **Orders** restores the current job.
* Trigger runs, message outcomes, and order commits use stable idempotency. An
  automatic continuation or retry does not replay successful receipts.
* **Resume Import** appears on recoverable historical errors. It safely
  reschedules the stored scan or import attempt, or returns directly to review
  when parsing already finished. **Retry Failed** selects failed messages only.
* **Cancel Import** terminalizes the job, discards its pending review drafts,
  and attempts to cancel known scan/import runs. If provider cancellation is
  incomplete, the app reports that truthfully and late writes remain blocked.

## Duplicate and counter guarantees

* One Gmail message ID can create at most one order per user.
* Repeated callbacks and retries are idempotent.
* `totalImported` counts newly successful orders only, not candidates,
  duplicates, no-item results, or failures.
* Incremental history cursors do not advance across an incomplete bounded
  discovery window.

## Privacy and disconnect

| Data                          | Handling                                                                                       |
| ----------------------------- | ---------------------------------------------------------------------------------------------- |
| OAuth token                   | Held by Clerk and fetched server-side for a task; never stored in the app.                     |
| Raw email body                | Processed in Trigger.dev task memory and not persisted.                                        |
| Candidate metadata            | Stored temporarily in paged, owner-scoped candidate child records, then purged.                |
| Import outcome                | One owner-scoped, idempotent child record per message supports partial retry and continuation. |
| Parsed order data             | Staged in a user-owned review draft, then stored in order history only after confirmation.     |
| Community domain contribution | Domain intelligence is shared without linking the shared row to a user ID.                     |

Disconnecting Gmail first closes local write boundaries and invalidates the
connection generation so late callbacks cannot write. High IQ then attempts to
cancel known background runs and revoke the delegated Gmail token. Imported
orders remain in the account.

## Current limitations

* Photo and image receipt parsing is outside this flow.
* Changing a saved order's strain identity after commit requires adding a
  corrected order so matching, confirmation, research, and Stash effects can
  run through one trustworthy boundary again.

<CardGroup cols={2}>
  <Card title="Order Activation" icon="receipt" href="/help/user-flows/order-upload">
    Full implemented flow, including strain confirmation and durable save.
  </Card>

  <Card title="Manage Shops" icon="store" href="/help/features/dispensaries">
    Understand shop fields and Gmail readiness.
  </Card>

  <Card title="Sync Troubleshooting" icon="wrench" href="/help/troubleshooting/sync-problems">
    Recover from connection, scan, and import failures.
  </Card>

  <Card title="Gmail Architecture" icon="diagram-project" href="/guides/platform/gmail-sync">
    Technical system boundaries and durable job states.
  </Card>
</CardGroup>
