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

# Snowflake Integration

> Connect Snowflake to Statisfy to sync product usage, custom fields, and custom objects with self-serve query configuration.

### Connect Snowflake with Statisfy

The Snowflake integration lets you import data from your Snowflake warehouse into Statisfy. Author queries in the Statisfy settings UI, preview against your warehouse, and schedule them — sync product usage, account-level custom fields, person-level attributes, or custom objects.

Snowflake uses the same self-serve configuration model as the other warehouse integrations. You can find the shared concepts — query types, account resolvers, transformers, schedules, configuration history — in [Integration Concepts](/integrations/self_serve_configuration). This page focuses on what's specific to Snowflake.

**Prerequisites:**

* **Admin access** to Statisfy
* A Snowflake account with a dedicated user/role for Statisfy
* The user must have `USAGE` on a warehouse and `SELECT` on the schemas/tables you want to sync
* Credentials: password **or** PKCS8 private key

### What You Can Import

| Data Type          | Description                           | Use Case                                     |
| ------------------ | ------------------------------------- | -------------------------------------------- |
| **Product Usage**  | Time-series usage metrics per account | MAU, API calls, feature usage                |
| **Custom Fields**  | Account- or person-level attributes   | Health scores, segments, industry, plan tier |
| **Custom Objects** | Domain-specific records               | Subscriptions, deployments, contracts        |

### Authentication Methods

Snowflake supports two authentication options.

<Accordion title="Private Key Authentication (recommended)">
  Connect using a key pair instead of a password. Better for production — keys are not exposed during interactive sessions and rotate independently of human users.

  **Required credentials:**

  * Account identifier (e.g., `xy12345.us-east-1`)
  * Username
  * **Private key** file in PEM format with **PKCS8** encoding
  * Passphrase (only if the key is encrypted)
  * Default warehouse
  * Default database
  * Default schema

  Generate a key pair following the [Snowflake key-pair docs](https://docs.snowflake.com/en/user-guide/key-pair-auth), then assign the public key to your service user with `ALTER USER ... SET RSA_PUBLIC_KEY = '...';`.
</Accordion>

<Accordion title="Password Authentication">
  Connect using username and password.

  **Required credentials:**

  * Account identifier
  * Username
  * Password
  * Default warehouse
  * Default database
  * Default schema

  Suitable for trials or short-lived setups; switch to key-pair auth for long-running production use.
</Accordion>

### Set Up the Service User

Run, as `ACCOUNTADMIN` (or a role with equivalent privileges):

```sql theme={null}
-- 1. Create a dedicated role and warehouse
CREATE ROLE IF NOT EXISTS statisfy_reader;
CREATE WAREHOUSE IF NOT EXISTS statisfy_wh
  WAREHOUSE_SIZE = XSMALL
  AUTO_SUSPEND   = 60
  INITIALLY_SUSPENDED = TRUE;
GRANT USAGE ON WAREHOUSE statisfy_wh TO ROLE statisfy_reader;

-- 2. Grant read access on the schemas Statisfy should see
GRANT USAGE ON DATABASE analytics TO ROLE statisfy_reader;
GRANT USAGE ON SCHEMA analytics.product TO ROLE statisfy_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA analytics.product TO ROLE statisfy_reader;
GRANT SELECT ON FUTURE TABLES IN SCHEMA analytics.product TO ROLE statisfy_reader;

-- 3. Create the service user
CREATE USER IF NOT EXISTS statisfy_svc
  PASSWORD          = '<temp-rotate-after-first-login>'
  DEFAULT_ROLE      = statisfy_reader
  DEFAULT_WAREHOUSE = statisfy_wh;
GRANT ROLE statisfy_reader TO USER statisfy_svc;
```

Adjust the database / schema names to match your environment.

### Steps to Connect

1. **Log in to Statisfy.**

2. Navigate to **Integrations → Admin Apps → Snowflake → Connect**.

3. Pick **Private Key** or **Password** authentication and fill in the fields:
   * **Account** — your Snowflake account identifier (host without `.snowflakecomputing.com`)
   * **Username** — the service user
   * **Private Key / Password** — credential matching the method you chose
   * **Default Warehouse / Database / Schema** — used for queries that don't fully qualify their objects

4. Click **Test Connection** to confirm Statisfy can authenticate and run a no-op query.

5. Once connected, Snowflake will appear as **Connected** on the Integrations page.

### Configure Queries

Open **Integrations → Snowflake → Settings** to:

* **Browse databases, schemas, and tables** the service user can see, with column types
* **Author queries** using Snowflake SQL with autocomplete and a preview pane
* **Map results** to Statisfy accounts (via Statisfy account ID, CRM ID, organization ID, email domain, account name, or any custom field) and to fields, metrics, or custom objects
* **Apply column transformers** to reshape values before they're written
* **Set the cadence** — daily, weekly, monthly, or a sub-day interval (HOURLY through TWELVE\_HOURS)
* **Run a one-off sync** on demand

Each saved query is one of three types — `product_usage`, `custom_field`, or `custom_object`. See [Query types](/integrations/self_serve_configuration#query-types) and [Account resolvers](/integrations/self_serve_configuration#account-resolvers) for the shared model.

### Snowflake-Specific Notes

* **Fully qualify objects across databases.** If a query references a table outside the default database / schema, qualify it explicitly: `OTHER_DB.SCHEMA.TABLE`.
* **Date placeholders.** Use `{START_DATE}` / `{END_DATE_SQL}` to keep queries incremental. Snowflake's `DATE_TRUNC()`, `DATEADD()`, and `TO_DATE()` work well with these placeholders.
* **Warehouse cost.** Each query consumes warehouse credits. Use a small (`XSMALL`/`SMALL`) warehouse with `AUTO_SUSPEND = 60` to minimize idle cost, and rely on Snowflake result caching for repeat scans.
* **Case sensitivity.** Snowflake uppercases unquoted identifiers. Quote columns and tables if your warehouse uses mixed-case identifiers, otherwise stick to uppercase consistently in the query.

### Account Matching

| Resolver                | Description                              |
| ----------------------- | ---------------------------------------- |
| **Statisfy Account ID** | Native Statisfy account identifier       |
| **CRM Account ID**      | Salesforce or HubSpot account identifier |
| **Organization ID**     | External org identifier                  |
| **Email Domain**        | Company website domain                   |
| **Account Name**        | Company name (fuzzy matching)            |
| **Custom Field**        | Any custom field defined on accounts     |

<Warning>
  Rows that don't resolve to an existing Statisfy account are skipped. For CRM ID resolvers, make sure your CRM integration has synced the matching accounts first.
</Warning>

For `custom_field` queries that target people instead of accounts, configure a **person resolver** (email column, optionally name) — Statisfy will upsert the person record by email.

### Sync Behavior

**Scheduled Jobs:**

* Each saved query runs on its own cadence.
* The first run after connecting is a **bootstrap** covering the last 30 days; subsequent runs cover only the active window for the cadence.
* Self-serve configuration takes precedence over any built-in fallback set up by support.

**Error Handling:**

* Per-query errors are logged but do not block other queries from running.
* Invalid rows within a query are skipped and reported in the job audit log.

### Network Access

If your Snowflake account uses **network policies** to restrict access by IP, allow Statisfy's egress IPs:

```text theme={null}
35.203.185.27
35.197.52.231
```

Configure these via `CREATE NETWORK POLICY` and assign the policy to your service user.

### Security

* Credentials are stored encrypted in Google Cloud Secret Manager.
* Private key authentication is recommended for production.
* All connections use TLS.
* Queries authored in the Settings page are read-only — Statisfy validates each query and rejects DDL/DML before save.
* Access is scoped to whatever the service user's role can see — grant only the schemas you want Statisfy to read.

### Troubleshooting

<Accordion title="Authentication failed">
  **Password auth:**

  * Confirm the account identifier is correct (host minus `.snowflakecomputing.com`)
  * Confirm the password hasn't expired or rotated

  **Private key auth:**

  * The key must be in **PEM** format with **PKCS8** encoding
  * Confirm the passphrase is correct (if the key is encrypted)
  * Confirm the public key has been assigned to the service user (`DESC USER ... ;` → `RSA_PUBLIC_KEY`)
</Accordion>

<Accordion title="Schema or tables not visible in the browser">
  * Confirm the service user's role has `USAGE` on the database and schema and `SELECT` on the tables
  * `INFORMATION_SCHEMA` and system schemas are intentionally hidden
  * If you recently granted access, the picker may need to be reloaded
</Accordion>

<Accordion title="Query validation errors at save time">
  * Statisfy validates queries against the Snowflake SQL dialect — vendor-specific functions from other warehouses will be flagged
  * DDL (`CREATE`, `DROP`) and DML (`INSERT`, `UPDATE`, `DELETE`, `MERGE`) are rejected — only read-only queries are allowed
  * Check the validation error for the offending function or syntax
</Accordion>

<Accordion title="Records not matching to accounts">
  * Verify the resolver column contains values that exist in Statisfy
  * For CRM ID resolvers, confirm your CRM integration has synced the matching accounts
  * Try a different resolver (switch from account name to email domain) if matching is unreliable
  * Add a `regex_extract` or `strip_prefix` transformer if the column contains the right ID with extra characters
</Accordion>

<Accordion title="Sync is slow or running up credits">
  * Drop the warehouse size to `XSMALL` for read-only sync queries
  * Lower the cadence to `DAILY` so each run scans a smaller window
  * Use `{START_DATE}` / `{END_DATE_SQL}` to keep queries incremental rather than scanning the full table
</Accordion>

### Need Help?

For initial setup, query design, or troubleshooting, contact [support@statisfy.com](mailto:support@statisfy.com).
