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

# Data Export

> Export your Minoa data to BigQuery, Snowflake, or Google Sheets on a recurring schedule

Minoa's Data Export feature lets you automatically sync **business cases** from your workspace to your own data warehouse or Google Sheets. Once configured, exports run on a schedule you choose — hourly, daily, weekly, or monthly — keeping your destination up to date with the latest Minoa data.

This enables you to join Minoa data with your existing datasets, build custom dashboards, and run advanced analytics in your own BI tools.

<Info>
  Data Export is available as an early access feature. Contact your Minoa account team to enable it for your organization.
</Info>

***

## Supported Destinations

<Columns cols={3}>
  <Card title="Google BigQuery" icon="google">
    Authenticate with a GCP service account JSON key file. Data is written directly to a BigQuery table in your project.
  </Card>

  <Card title="Snowflake" icon="snowflake">
    Authenticate with RSA key-pair credentials. Data is written via Snowflake's SQL REST API to a table in your database.
  </Card>

  <Card title="Google Sheets" icon="google">
    Authenticate with a GCP service account JSON key file. Data is written to a tab in a Google Spreadsheet shared with the service account.
  </Card>
</Columns>

***

## Exported data

Each export contains **business cases** in your workspace, flattened to **one row per opportunity** that has a business case.

| Object         | Description                                   | Columns                                                                                                                                                                                                                                                  |
| -------------- | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Business Cases | All qualifying business cases for your tenant | 27 columns including identifiers, name, status, stage, account, owner, currency, benefit and investment totals, ROI and payback, contract fields, use case count, CRM linkage, flags, usage score, scenario mode, value realized to date, and timestamps |

<Tip>
  You can preview the exact column schema when creating or editing an export by expanding **View object schema** in the Data Export settings.
</Tip>

***

## Export Methods

| Method          | Behavior                                                                                                       | Best For                                                  |
| --------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| **Incremental** | Only exports records created or updated since the last successful run                                          | Large datasets where you want to minimize transfer volume |
| **Full**        | Truncates the table and re-exports all records on every run                                                    | Smaller datasets or when you need a complete refresh      |
| **Upsert**      | Inserts new records and updates existing rows in-place using the record ID. *Not available for Google Sheets.* | Maintaining a single up-to-date copy of each record       |

***

## Setting Up BigQuery

### 1. Create a Service Account

<Steps>
  <Step title="Open the GCP Console">
    Go to the [Google Cloud Console](https://console.cloud.google.com) and select the project where your target dataset lives.
  </Step>

  <Step title="Create a service account">
    Navigate to **IAM & Admin** → **Service Accounts** → **Create Service Account**.

    Give it a descriptive name like `minoa-data-export` and click **Create and Continue**.
  </Step>

  <Step title="Grant permissions">
    Assign the following roles to the service account:

    * **BigQuery Data Editor** (`roles/bigquery.dataEditor`) — allows creating tables and writing data
    * **BigQuery Job User** (`roles/bigquery.jobUser`) — allows running queries

    Click **Continue** → **Done**.
  </Step>

  <Step title="Generate a JSON key">
    Click on your new service account, go to the **Keys** tab, and click **Add Key** → **Create new key** → **JSON**.

    Download the JSON key file — you'll upload this to Minoa in the next step.

    <Warning>
      Keep this file secure. It grants write access to your BigQuery dataset. Do not commit it to version control or share it publicly.
    </Warning>
  </Step>
</Steps>

### 2. Create the Target Dataset

If you don't already have a dataset for Minoa data, create one:

<Steps>
  <Step title="Go to BigQuery">
    In the GCP Console, navigate to **BigQuery** → **SQL Workspace**.
  </Step>

  <Step title="Create a dataset">
    Click your project name in the explorer panel, then click **Create Dataset**.

    Choose a dataset ID (e.g., `minoa_exports`), select a data location, and click **Create Dataset**.
  </Step>
</Steps>

<Note>
  You do not need to create the table manually — Minoa will create it automatically on the first export run using the correct schema.
</Note>

### Minimum Permissions Summary

| Permission                   | Role                 | Why                                  |
| ---------------------------- | -------------------- | ------------------------------------ |
| `bigquery.tables.create`     | BigQuery Data Editor | Create the export table on first run |
| `bigquery.tables.updateData` | BigQuery Data Editor | Insert, update, and truncate rows    |
| `bigquery.tables.get`        | BigQuery Data Editor | Read table metadata                  |
| `bigquery.jobs.create`       | BigQuery Job User    | Execute queries                      |

***

## Setting Up Google Sheets

Google Sheets uses the same GCP service account authentication as BigQuery. You'll create a service account, enable the Google Sheets API, and share your spreadsheet with the service account.

### 1. Create a Service Account and JSON Key

<Steps>
  <Step title="Open the GCP Console">
    Go to the [Google Cloud Console](https://console.cloud.google.com) and select (or create) a project.
  </Step>

  <Step title="Create a service account">
    Navigate to **IAM & Admin** → **Service Accounts** → **Create Service Account**.

    Give it a descriptive name like `minoa-sheets-export` and click **Create and Continue**.
  </Step>

  <Step title="Skip role assignment">
    You do not need to assign any IAM roles — the service account gets access to the spreadsheet through sharing (next section). Click **Continue** → **Done**.
  </Step>

  <Step title="Generate a JSON key">
    Click on your new service account, go to the **Keys** tab, and click **Add Key** → **Create new key** → **JSON**.

    Download the JSON key file — you'll upload this to Minoa in a later step.

    <Warning>
      Keep this file secure. It grants access to any spreadsheet shared with the service account. Do not commit it to version control or share it publicly.
    </Warning>
  </Step>
</Steps>

### 2. Enable the Google Sheets API

<Steps>
  <Step title="Open the API Library">
    In the GCP Console, navigate to **APIs & Services** → **Library**.
  </Step>

  <Step title="Enable the API">
    Search for **Google Sheets API**, click the result, and click **Enable**.

    If it already shows "API Enabled", no action is needed.
  </Step>
</Steps>

### 3. Share the Spreadsheet with the Service Account

<Steps>
  <Step title="Find your service account email">
    Open the JSON key file you downloaded. The `client_email` field contains the service account email address — it looks like `minoa-sheets-export@your-project.iam.gserviceaccount.com`.
  </Step>

  <Step title="Share the spreadsheet">
    Open your Google Spreadsheet in a browser. Click **Share**, paste the service account email, set the permission to **Editor**, uncheck "Notify people", and click **Share**.
  </Step>

  <Step title="Note the Spreadsheet ID and sheet name">
    The **Spreadsheet ID** is the long string in the URL between `/d/` and `/edit`:

    ```
    https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit
    ```

    The **sheet name** is the tab name at the bottom of the spreadsheet (default is `Sheet1`).
  </Step>
</Steps>

<Note>
  You do not need to add headers manually — Minoa writes the header row automatically on the first export run.
</Note>

### Minimum Permissions Summary

| Permission               | How It's Granted                                  | Why                                               |
| ------------------------ | ------------------------------------------------- | ------------------------------------------------- |
| Google Sheets API access | Enabled on the GCP project                        | Allows the service account to call the Sheets API |
| Spreadsheet Editor       | Spreadsheet shared with the service account email | Read and write data in the spreadsheet            |

### Limitations

<Warning>
  Google Sheets has a hard limit of **10 million cells** per spreadsheet. Performance begins to degrade above roughly 50,000 rows. For large or fast-growing datasets, consider using BigQuery or Snowflake instead.
</Warning>

***

## Setting Up Snowflake

### 1. Generate an RSA Key Pair

Snowflake's SQL REST API uses key-pair authentication. You'll generate an RSA key pair, register the public key with your Snowflake user, and provide the private key to Minoa.

<Steps>
  <Step title="Generate a private key">
    Run the following command in your terminal:

    ```bash theme={null}
    openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out minoa_rsa_key.p8 -nocrypt
    ```

    This creates an unencrypted PKCS#8 private key file called `minoa_rsa_key.p8`.

    <Warning>
      Keep this private key secure. It authenticates write access to your Snowflake database. Do not commit it to version control or share it publicly.
    </Warning>
  </Step>

  <Step title="Extract the public key">
    ```bash theme={null}
    openssl rsa -in minoa_rsa_key.p8 -pubout -out minoa_rsa_key.pub
    ```
  </Step>

  <Step title="Get the public key value">
    Copy the public key content without the header and footer lines:

    ```bash theme={null}
    grep -v "PUBLIC KEY" minoa_rsa_key.pub | tr -d '\n'
    ```

    Copy the output — you'll need it in the next step.
  </Step>
</Steps>

### 2. Create a Snowflake User and Assign the Key

<Steps>
  <Step title="Create a dedicated user (recommended)">
    Connect to your Snowflake account as an admin and run:

    ```sql theme={null}
    CREATE USER minoa_export_user
        DEFAULT_ROLE = minoa_export_role
        DEFAULT_WAREHOUSE = COMPUTE_WH;
    ```
  </Step>

  <Step title="Assign the public key">
    ```sql theme={null}
    ALTER USER minoa_export_user SET RSA_PUBLIC_KEY='<paste your public key here>';
    ```

    Paste the public key value (without header/footer) that you copied in the previous section.
  </Step>

  <Step title="Create a role with minimum privileges">
    ```sql theme={null}
    CREATE ROLE minoa_export_role;

    -- Grant usage on warehouse, database, and schema
    GRANT USAGE ON WAREHOUSE COMPUTE_WH TO ROLE minoa_export_role;
    GRANT USAGE ON DATABASE MINOA_DB TO ROLE minoa_export_role;
    GRANT USAGE ON SCHEMA MINOA_DB.PUBLIC TO ROLE minoa_export_role;

    -- Grant table-level permissions on the target schema
    GRANT CREATE TABLE ON SCHEMA MINOA_DB.PUBLIC TO ROLE minoa_export_role;
    GRANT SELECT, INSERT, UPDATE, DELETE, TRUNCATE ON ALL TABLES IN SCHEMA MINOA_DB.PUBLIC TO ROLE minoa_export_role;
    GRANT SELECT, INSERT, UPDATE, DELETE, TRUNCATE ON FUTURE TABLES IN SCHEMA MINOA_DB.PUBLIC TO ROLE minoa_export_role;

    -- Assign the role to the user
    GRANT ROLE minoa_export_role TO USER minoa_export_user;
    ```

    <Tip>
      Replace `COMPUTE_WH`, `MINOA_DB`, and `PUBLIC` with your actual warehouse, database, and schema names.
    </Tip>
  </Step>
</Steps>

### Minimum Permissions Summary

| Permission     | Granted On | Why                                  |
| -------------- | ---------- | ------------------------------------ |
| `USAGE`        | Warehouse  | Execute queries                      |
| `USAGE`        | Database   | Access the database                  |
| `USAGE`        | Schema     | Access the schema                    |
| `CREATE TABLE` | Schema     | Create the export table on first run |
| `SELECT`       | Tables     | Read data for MERGE operations       |
| `INSERT`       | Tables     | Write new rows                       |
| `UPDATE`       | Tables     | Update existing rows (upsert)        |
| `DELETE`       | Tables     | Required for MERGE operations        |
| `TRUNCATE`     | Tables     | Clear table for full exports         |

***

## Security

Minoa is designed to meet enterprise security requirements for data export:

* **Network egress** — Minoa can provide a fixed egress IP address for data export traffic upon request, making it easy to add Minoa to your firewall allowlist or network policy. Contact your Minoa account team for details.
* **Tightly scoped permissions** — Each destination setup above uses the minimum permissions necessary. Minoa never requires admin-level access to your data warehouse.
* **Dedicated credentials** — We recommend creating a purpose-built service account (GCP) or user (Snowflake) exclusively for Minoa exports, separate from any human user accounts. This simplifies auditing and lets you revoke access independently.

<Tip>
  If your data warehouse is behind a firewall or VPN, contact your Minoa account team to obtain a fixed egress IP address for whitelisting before running your first export.
</Tip>

***

## Configuring an Export in Minoa

<Steps>
  <Step title="Navigate to Data Export">
    In Minoa, go to **Settings** → **Data Export** and click **New Export**.
  </Step>

  <Step title="Name your export">
    Enter a descriptive name, e.g., `BigQuery - Business Cases` or `Snowflake - Business Cases`.
  </Step>

  <Step title="Select your destination">
    Choose **BigQuery**, **Snowflake**, or **Google Sheets**.
  </Step>

  <Step title="Provide credentials">
    * **BigQuery** / **Google Sheets**: Upload the service account JSON key file you downloaded earlier.
    * **Snowflake**: Enter your Snowflake username and paste the contents of the private key file (`minoa_rsa_key.p8`).
  </Step>

  <Step title="Configure the destination">
    * **BigQuery**: Enter your GCP Project ID, Dataset ID, and a Table ID (e.g., `business_cases`).
    * **Snowflake**: Enter your Account identifier (e.g., `orgname-accountname`), Database, Schema, Table, and Warehouse.
    * **Google Sheets**: Enter the Spreadsheet ID (from the spreadsheet URL) and the sheet (tab) name.
  </Step>

  <Step title="Set interval and export method">
    Choose how often to run the export and whether to use **Incremental**, **Full**, or **Upsert** (see [Export Methods](#export-methods)). Data Export covers business cases only.
  </Step>

  <Step title="Test and save">
    Use the **Start test** button to verify your configuration before saving. Check the **Runs** tab to confirm the test completed successfully.
  </Step>
</Steps>

<Check>
  Once saved and enabled, your export will run automatically on the schedule you configured.
</Check>

***

## Monitoring Exports

### Runs Tab

The **Runs** tab shows a history of all export executions:

* **Status** — Green (completed), yellow (completed with errors), red (failed), or blue (running)
* **Rows Exported** — Number of records written to the warehouse
* **Duration** — How long the export took
* **Errors** — Count of any errors encountered

### Logs Tab

The **Logs** tab provides detailed log entries across all runs. You can filter by:

* **Level** — INFO, WARN, or ERROR
* **Search** — Search log messages or filter by run ID

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Export fails with 'permission denied'">
    Verify that your service account (BigQuery / Google Sheets) or Snowflake user has the minimum permissions listed above. For BigQuery, ensure both **BigQuery Data Editor** and **BigQuery Job User** roles are assigned. For Snowflake, confirm the role grants include `USAGE` on the warehouse, database, and schema. For Google Sheets, confirm the spreadsheet is shared with the service account email as an **Editor**.
  </Accordion>

  <Accordion title="Table is not being created automatically">
    Minoa creates the target table on the first export run. Ensure your credentials have `CREATE TABLE` permission on the target dataset (BigQuery) or schema (Snowflake). If the table already exists with a different schema, the export may fail — drop or rename the existing table and let Minoa recreate it.
  </Accordion>

  <Accordion title="Snowflake authentication errors">
    * Confirm the private key is in **PKCS#8 PEM format** (starts with `-----BEGIN PRIVATE KEY-----`).
    * Verify the matching public key is registered on the Snowflake user: run `DESC USER minoa_export_user` and check the `RSA_PUBLIC_KEY` property.
    * Ensure the account identifier matches exactly (e.g., `orgname-accountname`). You can find this in your Snowflake URL: `https://<account>.snowflakecomputing.com`.
  </Accordion>

  <Accordion title="Exports show 'completed with errors'">
    Some records may fail to flatten or write due to unexpected data formats. Check the **Logs** tab for specific error messages. Common causes include invalid date values or extremely long text fields. The export will still write all records that succeed.
  </Accordion>

  <Accordion title="Data appears stale or not updating">
    * Check that the export status is **Enabled** in the Configuration tab.
    * Verify the interval matches your expectations (e.g., daily exports run once per day).
    * For **Incremental** exports, only records modified since the last successful run are included. If no records changed, the export will complete with 0 rows — this is expected.
  </Accordion>

  <Accordion title="Google Sheets export fails with 'sheet not found'">
    The sheet (tab) name you entered in Minoa must match exactly. Open the spreadsheet and check the tab name at the bottom. Names are case-sensitive. If the tab doesn't exist, create it in the spreadsheet before running the export.
  </Accordion>

  <Accordion title="Google Sheets API is not enabled">
    If you see an error mentioning the Sheets API, go to the [GCP Console](https://console.cloud.google.com) → **APIs & Services** → **Library**, search for **Google Sheets API**, and click **Enable**. Make sure you're in the same project that issued the service account key.
  </Accordion>

  <Accordion title="Google Sheets is approaching its cell limit">
    Google Sheets supports a maximum of 10 million cells per spreadsheet. If your exports are generating warnings about cell usage, consider switching to BigQuery or Snowflake, reducing the export frequency, or using a new spreadsheet.
  </Accordion>

  <Accordion title="Export fails with a connection timeout or network error">
    If your data warehouse is behind a firewall or your organization restricts traffic by IP address, you may need to whitelist Minoa's egress IP. See the [Security](#security) section above for details, and contact your Minoa account team to obtain the address.
  </Accordion>
</AccordionGroup>
