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

# Snowflake

## Overview

Stigg's integration with Snowflake allows you to export your product catalog, customer, and subscription data directly to your Snowflake account for custom reporting and analysis.

<Note>
  Stigg's native data export integrations are included in the Scale plan, and are also available as an optional add-on to the Growth plan. See Stigg's pricing for more details.
</Note>

<Card title="View the full entity schema" icon="sitemap" href="./schema">
  See every table and column exported to your destination, organized by entity group.
</Card>

## Setting up the integration

<Note>
  This guide describes the current connect flow. If your Snowflake connect form instead asks you to generate your own key pair (or offers a username/password option) rather than a **Create keys** button, your account hasn't moved to this flow yet — [contact Stigg support](mailto:support@stigg.io) rather than following the steps below.
</Note>

### Prerequisites

To set up the integration, you'll need a Snowflake account with the [ACCOUNTADMIN](https://docs.snowflake.com/en/user-guide/security-access-control-considerations.html) role. If you don't have an account with the ACCOUNTADMIN role, contact your Snowflake administrator to set one up for you.

<Note>
  Stigg connects to Snowflake using **key-pair authentication** only — there's no username/password option. Stigg generates the key pair for you as part of setup.
</Note>

<Steps>
  <Step title="Enter your connection details">
    In [Stigg](https://app.stigg.io/), navigate to **Integrations > Apps > Snowflake**.

    Enter the following information in the connection form:

    | Field        | Description                                                                                                                                                                                                                                                                           |
    | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | Account host | Your [Snowflake account host](https://docs.snowflake.com/en/user-guide/organizations-connect#connecting-with-a-url), for example: `ABC12345-XY67890.snowflakecomputing.com`. This must be your account host, not your `app.snowflake.com` web app address — that address is rejected. |
    | Port         | Defaults to `443`. Only change this if your network requires a different port.                                                                                                                                                                                                        |
    | Database     | The database to sync data into, for example: `STIGG_DB`                                                                                                                                                                                                                               |
    | Schema       | The schema to sync data into, for example: `STIGG_SCHEMA`                                                                                                                                                                                                                             |
    | Username     | The Snowflake user Stigg will connect as, for example: `STIGG_TRANSFER_USER`                                                                                                                                                                                                          |

    <Note>
      Role and warehouse aren't fields in this form — Snowflake uses the user's `default_role` and `default_warehouse`, which the setup script in the next step sets for you.
    </Note>

    Click **Create keys** to have Stigg generate an RSA key pair for this connection, then click **Continue**.
  </Step>

  <Step title="Run the setup script">
    Stigg generates a setup script based on the details you entered in the previous step, with your new public key already filled in. Copy it and run it in a [Snowflake worksheet](https://docs.snowflake.com/en/user-guide/ui-worksheet.html), using an account with the ACCOUNTADMIN role, with the **Run All** option (⌘ + Shift + Enter on Mac, CTRL + Shift + Enter on Windows).

    <CodeGroup>
      ```sql sql theme={null}

      -- set variables (these need to be uppercase)
      set export_role = 'STIGG_TRANSFER_ROLE';
      set export_warehouse = 'STIGG_TRANSFER_WH';
      set export_database = 'STIGG_DB';
      set export_schema = 'STIGG_SCHEMA';
      set export_username = 'STIGG_TRANSFER_USER';

      begin;

      -- create role
      use role accountadmin;
      create role if not exists identifier ($export_role);

      -- grant the role to sysadmin so admins can query the synced tables
      grant role identifier ($export_role) to role sysadmin;

      -- create a service user, then set its attributes with ALTER rather than inline on CREATE.
      -- if the user already exists (e.g. you're re-running this after the connect wizard
      -- regenerated your key pair), inline attributes on CREATE ... IF NOT EXISTS are silently
      -- skipped — the user keeps its old rsa_public_key and the connection fails with
      -- JWT_TOKEN_INVALID_PUBLIC_KEY_FINGERPRINT_MISMATCH with no indication why. The ALTER
      -- statements below always apply, so re-running this script is safe.
      create user if not exists identifier ($export_username);
      alter user identifier ($export_username) set type = service;
      alter user identifier ($export_username) set default_role = $export_role;
      alter user identifier ($export_username) set default_warehouse = $export_warehouse;
      alter user identifier ($export_username) set rsa_public_key = '<STIGG FILLS IN YOUR GENERATED PUBLIC KEY HERE>';

      grant role identifier ($export_role) to user identifier ($export_username);

      -- change role to accountadmin for warehouse / database steps
      use role accountadmin;

      -- create warehouse
      create warehouse if not exists identifier ($export_warehouse)
          warehouse_size = 'XSMALL'
          auto_suspend = 60
          auto_resume = true
          initially_suspended = true;

      grant usage on warehouse identifier ($export_warehouse) to role identifier ($export_role);

      -- create database and schema
      create database if not exists identifier ($export_database);
      create schema if not exists identifier ($export_database || '.' || $export_schema);

      -- grant privileges
      grant ownership on schema identifier ($export_database || '.' || $export_schema) to role identifier ($export_role);
      grant usage on database identifier ($export_database) to role identifier ($export_role);

      -- hand over any table already in this schema (for example from a previous export into it).
      -- Stigg rebuilds a table whenever its structure changes, and in Snowflake that needs OWNERSHIP
      -- of the table. This is a no-op on a new schema.
      grant ownership on all tables in schema identifier ($export_database || '.' || $export_schema)
          to role identifier ($export_role) copy current grants;

      commit;
      ```
    </CodeGroup>

    <Note>
      This script requires the ACCOUNTADMIN role. The role, warehouse, database, schema, and username shown match the values you entered in the previous step, and your generated public key is already inlined — copy the script exactly as Stigg shows it to you, rather than the version above.
    </Note>

    <Note>
      Two things to know about the ownership statement, if you're syncing into a schema that isn't brand new:

      * `copy current grants` preserves the privileges your own roles already hold on those tables, so handing ownership to Stigg's role doesn't cut your consumers off. If the schema also contains tables of your own, replace that statement with one `grant ownership on table <database>.<schema>.<table> to role $export_role copy current grants;` per exported table, so your tables stay yours.
      * A rebuilt table is a new object, so privileges granted directly on the old table don't carry over. If your own roles query the exported tables, grant them access at the schema level once — `grant select on future tables in schema <database>.<schema> to role <your_role>;` — and every rebuilt table stays readable.
    </Note>

    <Warning>
      Don't reload the page or reopen the connection wizard once your key pair has been generated. Doing so generates a new key pair, and the public key you already registered in Snowflake will no longer match.
    </Warning>

    Once you've run the script, click **Test & continue**. Stigg verifies the connection before proceeding.
  </Step>

  <Step title="Network policy (optional)">
    Only needed if your Snowflake account restricts access by IP. Run this in Snowflake as ACCOUNTADMIN to let Stigg's service user in from our data export IP addresses — it limits that user to those addresses and leaves your account-level network policy untouched, so run it against a user dedicated to Stigg. If your account has no IP restrictions, skip the script; the button below tests the connection either way.

    <CodeGroup>
      ```sql Snowflake network policy SQL theme={null}

      -- ============================================================
      -- Optional: allow Stigg's transfer service to reach Snowflake from its static IP addresses.
      -- Needed only if your Snowflake account restricts access by IP.
      -- Run as ACCOUNTADMIN, after the setup script from the previous step (the user has to exist already).
      -- ============================================================

      set user_name      = 'STIGG_TRANSFER_USER';

      use role accountadmin;

      -- Read this result before you run the rest: everything below reuses a policy of this name if one already
      -- exists, and replaces its allowlist. Empty means there is nothing to collide with. A row whose comment
      -- names Stigg is ours, from an earlier run. A row that is neither is your own policy sharing the name —
      -- rename it first. If it is owned by a role ACCOUNTADMIN cannot reach, the alter further down fails and
      -- stops the script, which is the safe direction: nothing has been attached to your user at that point.
      show network policies like 'STIGG_TRANSFER_NETWORK_POLICY';

      create network policy if not exists STIGG_TRANSFER_NETWORK_POLICY
        allowed_ip_list = (
          -- Stigg data export (US):
          '35.192.85.117/32',
          -- Stigg data export (EU):
          '104.199.49.149/32'
        )
        comment = 'Stigg data export egress addresses. Managed by the Stigg connect wizard.';

      -- The create above is skipped if the policy already exists, which would leave your user on that policy's
      -- allowlist instead of this one, so set the addresses explicitly here.
      alter network policy STIGG_TRANSFER_NETWORK_POLICY set allowed_ip_list = (
          -- Stigg data export (US):
          '35.192.85.117/32',
          -- Stigg data export (EU):
          '104.199.49.149/32'
      );

      -- A policy on the user overrides the one on the account, so this lets the transfer through without changing
      -- your account-level policy. It does replace any network policy currently on this user and limits them to
      -- the addresses above, so point it at a user dedicated to Stigg rather than one your own jobs log in as.
      -- To undo: alter user identifier($user_name) unset network_policy;
      alter user identifier($user_name) set network_policy = STIGG_TRANSFER_NETWORK_POLICY;
      ```
    </CodeGroup>

    <Warning>
      If you're migrating from Stigg's previous Airbyte-based Snowflake export, don't reuse an existing network policy that still allowlists Airbyte's IP addresses for this script — the `alter network policy ... set allowed_ip_list` statement above replaces the entire list, not just adds to it. Give this integration its own policy name (or add these addresses to your existing list instead of running the script as-is) until the Airbyte-based integration is fully retired, so you don't lock out a sync that's still running.
    </Warning>

    <Note>
      If a sync that was previously working starts failing silently after you've applied a network policy, and nothing else about your setup changed, check with [Stigg support](mailto:support@stigg.io) for the current list of export addresses before assuming your policy is misconfigured — it may have changed since this page was last updated.
    </Note>
  </Step>

  <Step title="Choose entities to export">
    Under **Configurations**, expand the **Entities to export** section to choose which entity groups to include in the sync. All groups are selected by default.

    See [Exported entities](./overview#exported-entities) for a description of each group.

    Click **Connect** to complete the setup.
  </Step>
</Steps>

## Reconnecting or rotating your key

Stigg doesn't store your Snowflake credentials, so connection details are read-only once the integration is connected. To rotate your key pair, or to change any connection detail (account host, database, schema, username, and so on), remove the existing integration (see [Removing the integration](./overview#removing-an-integration)) and set it up again using the steps above. A fresh key pair is generated each time you go through setup, so you'll need to register the new public key on your Snowflake user with the setup script from step 2.

<Note>
  There's currently no zero-downtime way to rotate the key pair. Removing the integration stops syncing until you've completed setup again — the disconnection lasts as long as it takes you to work through the steps above. Once reconnected, Stigg performs a full sync of all selected entities from scratch, the same as a brand-new connection, rather than resuming from where the previous integration left off. Your sync history from before the rotation is preserved and remains visible alongside the new integration's runs. If your organization requires rotation without an interruption in sync coverage, [contact Stigg support](mailto:support@stigg.io) before rotating.
</Note>


## Related topics

- [Exported entities](/documentation/importing-and-exporting-data/export/overview.md#exported-entities)
- [Sync process, schedule, manual sync, and sync history](/documentation/importing-and-exporting-data/export/overview.md#sync-process)
