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

# Snowflake

> Connect Serval to your Snowflake account with a Programmatic Access Token so workflows can run SQL and manage Snowflake objects on demand.

## About Snowflake

Snowflake is a cloud data platform for storing and querying data. Serval connects to a single Snowflake account using a Programmatic Access Token (PAT) and calls Snowflake's REST APIs - including the SQL Statement API and the object-management APIs - on demand from your workflows. There are no prebuilt helper functions: every workflow request goes through one generic "Snowflake API request" action, which Serval forwards to your connected account's domain with your token attached.

**Authentication:** Programmatic Access Token (PAT)

**Data sync:** On-demand only. Serval never syncs or ingests Snowflake data in the background - Snowflake is queried or modified only when a workflow step runs.

## What the Snowflake integration enables

| Capability                       | Description                                                                                                                                                                                                                            |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Execute SQL statements           | Run query, DML, and DDL statements through Snowflake's SQL Statement API, optionally specifying the database, schema, warehouse, role, bindings, and timeout for each statement.                                                       |
| Poll and fetch large result sets | Check the status of asynchronous or long-running statements and retrieve results partition by partition once they complete.                                                                                                            |
| Cancel running statements        | Stop a previously submitted statement that is still executing.                                                                                                                                                                         |
| Manage Snowflake objects         | Work with Snowflake's object-management APIs - databases, schemas, tables, views, warehouses, users, roles, grants, tasks, streams, pipes, stages, network policies and rules, and more - subject to the privileges of the PAT's role. |
| Use Cortex AI                    | Call Snowflake Cortex APIs, including Cortex Analyst, Cortex Inference, Cortex Search, and the OpenAI- and Anthropic-compatible Cortex endpoints.                                                                                      |

In total, the integration covers 46 Snowflake REST API surfaces. Anything defined in the [Snowflake API](https://docs.snowflake.com/en/developer-guide/snowflake-rest-api/snowflake-rest-api) can be accessed through Serval.

## Get your credentials

You'll create a Programmatic Access Token (PAT) for the Snowflake user Serval should act as - ideally a dedicated service user with a narrowly scoped role. See Snowflake's [Programmatic Access Tokens documentation](https://docs.snowflake.com/en/user-guide/programmatic-access-tokens) for full details.

<Steps>
  <Step title="Create a dedicated service user (recommended)">
    Using the `ACCOUNTADMIN` role, create a user just for Serval, e.g. `CREATE USER SERVAL_USER COMMENT = 'Service account for Serval integration';`
  </Step>

  <Step title="Create a scoped role and grant it to the user (recommended)">
    Create a role with only the privileges Serval needs (warehouse and database usage, access to the relevant schemas and tables), then assign it: `GRANT ROLE SERVAL_ROLE TO USER SERVAL_USER;`
  </Step>

  <Step title="Assign a network policy to the user">
    Snowflake requires service users to be covered by a network policy before a PAT can be generated or used for them (by default this applies to human users authenticating with a PAT too). Create a network rule that allow-lists Serval's egress IP addresses, wrap it in a network policy, and assign it: `ALTER USER SERVAL_USER SET NETWORK_POLICY = SERVAL_NETWORK_POLICY;`

    <Warning>
      Contact **[support@serval.com](mailto:support@serval.com)** to get the current list of Serval egress IPs for your network rule. Without a network policy assigned to the user, Snowflake refuses PAT authentication for service users.
    </Warning>
  </Step>

  <Step title="Generate the PAT">
    In Snowsight, go to **Profile → Programmatic access tokens**, or use SQL: `ALTER USER SERVAL_USER ADD PROGRAMMATIC ACCESS TOKEN serval_pat ROLE_RESTRICTION = 'SERVAL_ROLE' DAYS_TO_EXPIRY = 90;`

    By default a PAT expires after just 15 days, so set an explicit expiry that matches your rotation schedule.

    <Warning>
      Copy the token immediately - Snowflake shows it only once.
    </Warning>
  </Step>

  <Step title="Find your account URL">
    If your browser URL is `https://app.snowflake.com/<org>/<account>/...`, your account URL is `<org>-<account>.snowflakecomputing.com` - this form works regardless of which cloud your account runs on. Older locator-style addresses with extra labels (for example `xy12345.us-east-1.snowflakecomputing.com`) are also accepted. Or run: `SELECT CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT_NAME() || '.snowflakecomputing.com';`
  </Step>
</Steps>

## Connect in Serval

<Steps>
  <Step title="Open the Snowflake connect form">
    In Serval, go to **Applications**, open the **Available** tab, find **Snowflake**, and click **Connect**. The "Configure Snowflake" form appears.
  </Step>

  <Step title="Enter the Account URL (required)">
    Enter the bare account domain, e.g. `myorg-account123.snowflakecomputing.com` - no `https://` prefix, no path, and no stray spaces. The field's helper text reads "Your Snowflake account identifier (without https\://)". Multi-part domains like `account.region.cloud.snowflakecomputing.com` are accepted, and uppercase input is automatically lowercased when saving.

    If the value doesn't match the expected format, the form shows: `Invalid account URL. Expected format: <account>[.<region>].snowflakecomputing.com`. Serval's server applies the same checks when saving and responds with "accountUrl is required" or "invalid accountUrl format: must be a valid Snowflake account domain (e.g. account.region.snowflakecomputing.com)" if something slips through.
  </Step>

  <Step title="Enter the Access Token (required)">
    Paste the PAT into the **Access Token** password field (placeholder: "Programmatic Access Token"). The helper text reminds you where to create one: "Generate a PAT in Snowflake: Profile → Programmatic access tokens". Leaving it empty is rejected with "accessToken is required".
  </Step>

  <Step title="Click Submit">
    Serval checks the Account URL format and that a token was entered, then saves the connection. The token is stored encrypted.

    <Note>
      Serval does **not** make a live test call to Snowflake when you connect - a mistyped, expired, or under-privileged token is accepted here and only fails on first use.
    </Note>
  </Step>
</Steps>

Serval only ever sends your token to your own Snowflake address - hosts ending in .snowflakecomputing.com. Any other destination receives no credentials.

<Note>
  When editing the connection later (for example, to rotate a token), the saved Account URL appears pre-filled, but the Access Token field is always empty - Serval never displays the stored token, even in masked form. Every update must include a token: saving with the token field blank is rejected with "accessToken is required". Have the new PAT ready before you start.
</Note>

## Verifying the connection

This integration has no automated health checks, so a saved connection shows no pass/fail status on its own. To confirm your credentials work, run a trivial statement - such as `SELECT CURRENT_USER()` - through the "Snowflake API request" action in a test workflow. A successful response confirms the account URL, token, and network policy are all set up correctly.

<Tip>
  Because connect-time validation is format-only, a connection can save without errors and still fail on its first workflow request. If the very first call returns an authentication error, check the token value, its expiry, and the user's network policy - in that order.
</Tip>

## Gotchas and troubleshooting

<AccordionGroup>
  <Accordion title="Connection saved fine, but every request fails with an authentication error">
    Serval validates only the format of the account URL and the presence of the token at connect time - it never makes a live call to Snowflake. A typo'd, expired, or under-privileged PAT is accepted by the connect form and only fails later, typically as an authentication (401) error on the first workflow request. Re-check the token in Snowflake and re-enter it in the connection settings.
  </Accordion>

  <Accordion title="Snowflake rejects the token because no network policy is assigned">
    Snowflake requires service users to be covered by a network policy before their PATs can be used, and by default human users need one to authenticate with a PAT as well. Create a network rule allow-listing Serval's egress IPs (contact **[support@serval.com](mailto:support@serval.com)** for the list), wrap it in a network policy, and assign it to the user.
  </Accordion>

  <Accordion title="Requests suddenly start failing after working for a while">
    PATs expire - by default after just 15 days unless you set a longer expiry when creating the token. When the token expires, every request returns an authentication error. Generate a new PAT in Snowflake and update the connection's Access Token in Serval - ideally before the old one expires.
  </Accordion>

  <Accordion title="My account URL keeps getting rejected">
    The Account URL must be a bare `*.snowflakecomputing.com` domain. Values containing `https://`, a trailing path, stray spaces, or any other host are rejected with `Invalid account URL. Expected format: <account>[.<region>].snowflakecomputing.com`. Capitalization is never the problem - uppercase letters are lowercased automatically when the connection is saved.
  </Accordion>

  <Accordion title="Editing the connection asks for the token again">
    This is expected. The Access Token is write-only - Serval never displays the stored value - so the field is empty whenever you edit the connection, and saving with it blank is rejected. Keep the PAT value somewhere safe (or generate a fresh one) before re-saving the connection.
  </Accordion>

  <Accordion title="Some SQL statements are rejected by the SQL Statement API">
    Snowflake's SQL Statement API does not support PUT, GET, USE, ALTER SESSION, BEGIN, COMMIT, ROLLBACK, statements that set session variables, or statements that create temporary tables and stages. Instead of issuing USE statements, specify the database, schema, warehouse, and role in the statement request itself.
  </Accordion>

  <Accordion title="A long query returned a statement handle instead of results">
    If a statement doesn't finish within 45 seconds, Snowflake returns a statement handle instead of results, and the caller must poll the statement's status for completion (large results are returned in partitions). You can also set the async option to true to get the handle-based flow up front for known long-running statements.
  </Accordion>

  <Accordion title="I can't find any prebuilt Snowflake actions">
    There are none - the integration exposes a single generic action, "Snowflake API request", and no helper functions. All workflow interaction with Snowflake goes through that one action, which proxies an authenticated request to your account's domain.
  </Accordion>
</AccordionGroup>

***

Need help? Contact **[support@serval.com](mailto:support@serval.com)** for assistance with your Snowflake integration.
